V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  yjhatfdu2  ›  全部回复第 2 页 / 共 6 页
回复总数  103
1  2  3  4  5  6  
176 天前
回复了 freewind 创建的主题 数据库 请教多标签查询怎么做效率高?
@wxf666 这个索引占用 9G 左右,pg 的 GIN 是通用反向索引,并不是直接按照这样展开存的,原理类似 es 的反向索引
176 天前
回复了 freewind 创建的主题 数据库 请教多标签查询怎么做效率高?
@freewind 可以这样,也可以像#7 说的一样,每次用递归 CTE 把所有子层级标签查出来作为条件,这样标签层级可以更新,存储容量也可以小点,你们标签少可以考虑用更小的 int 做标签,也能省
176 天前
回复了 wanniwa 创建的主题 PostgreSQL Java 有没有针对 PostgreSQL 好用一点的 ORM
一般 ORM 都有 raw sql 的模式吧
176 天前
回复了 freewind 创建的主题 数据库 请教多标签查询怎么做效率高?
实测来了,
创建测试表,并插入 1 亿条测试数据,每一条包含 50 个随机标签,每个标签有 4000 种可能
create table tags_test(id serial primary key,tags array[int]);
create function random_array() returns int[] as $$ select array_agg((4000*random())::int) from generate_series(1,50)) $$;
insert into tags_test(tags) select random_array() from generate_series(1,100000000);
创建 GIN 索引
//最好临时增加 maintenance_work_mem ,会加快索引构建
//set maintenance_work_mem to 1GB;
create index ON tags_test using gin(tags);
简单查个包含几个 tags 的数据
postgres=# select count(*) from tags_test where tags @>array[1,2,3,4];
count
-------
2
(1 row)

Time: 135.185 ms
postgres=# select count(*) from tags_test where tags @>array[1,2,3];
count
-------
190
(1 row)

Time: 123.327 ms
当然,实际情况下标签肯定不是随机分布的,可能会更快或者更慢,也可以试试用 jsonb 来存和查,结果应该差不多
176 天前
回复了 1800x 创建的主题 Go 编程语言 有没有轻量级分布式消息队列
nats jetstream 只有 6 大概没有其他全符合
数据的话,用数据库原生的 publish 、subscribe 是最简单最优的,但是不能自动同步 DDL ,发生 DDL 后需要先在从库中更新 DDL 再继续订阅
176 天前
回复了 freewind 创建的主题 数据库 请教多标签查询怎么做效率高?
你这样完全没用上索引,你这个场景,最好就使用 postgresql ,使用 array 或者 json 存 tags ,然后建立 GIN 索引,然后每次查询把标签和子标签组成目标 tags ,然后用 select * from xxx where tags @> ARRAY[tag1,tag2,tag3],就可以用上 GIN 索引,一个亿数据也没啥
177 天前
回复了 qbmiller 创建的主题 Java 有 内嵌的简单 mysql 版本的 MQ 吗
也可以试试 nats jetstream ,部署极简单,可单机可集群,性能也很高
177 天前
回复了 qbmiller 创建的主题 Java 有 内嵌的简单 mysql 版本的 MQ 吗
redis 也能当 mq 用啊
看来 oracle 的优化器和性能都是有点挫了,pg 下毫无问题
使用 postgresql 的 jsonb ,可以使用 copy 快速导入,可以使用 jsonpath 快速查询,可以使用各种 json 相关函数和 json 聚合函数快速编辑和处理,而这些都只需要 SQL
198 天前
回复了 ihnfsa 创建的主题 云计算 自建数据湖方案
其实现在技术上几种数据糊技术核心的目的是解决传统 hadoop 系统中,parquet 等列存格式,难以支持 ACID 和事务的问题
198 天前
回复了 ihnfsa 创建的主题 云计算 自建数据湖方案
数据糊技术显然是为了写入和低成本优化的,查询速度会慢的离谱(正常场景下),例如使用 apache hudi ,即使使用了记录级索引,在 1TB20 亿行数据中使用索引取一行也要 12 秒,取 40000 行要 115 秒(来源 https://hudi.apache.org/blog/2023/11/01/record-level-index/),这在 RAG 的场景中简直是离谱
199 天前
回复了 ihnfsa 创建的主题 云计算 自建数据湖方案
开源数据糊一般是指 apache hudi 、apache iceberg 和 delta lake ,但这玩意儿都还是适合写入为主,偶尔批量计算的场景,不适合实时查询,和 AI Agent 、RAG 有啥关系?
find . -name '*.csv.gz' | xargs -I {} -P 4 bash -c "gzcat {} | psql -c 'copy test from stdin csv header'"
P 是并发,可以开高点
219 天前
回复了 zdking08135 创建的主题 程序员 请教一个系统设计题
@zdking08135 当然可以,不过按照这个编码形式,肯定要指定 country
220 天前
回复了 zdking08135 创建的主题 程序员 请教一个系统设计题
clickhouse 造一天数据试试看,单机 64 核 epyc 256G ram
建表,目前试下来效率最高的表结构
create table test4
(
time datetime CODEC (DoubleDelta, LZ4),
country UInt8 CODEC (DoubleDelta, LZ4),
province UInt8 CODEC (DoubleDelta, LZ4),
city UInt16 CODEC (DoubleDelta, LZ4),
uid UInt32
) engine = MergeTree() partition by toYYYYMMDD(time)
order by (time, country, province, city) settings index_granularity = 65536;

先造 10 亿数据,分布在一天内
insert into test4
select dateAdd(second, number / 1000000000, toDateTime('2024-04-02'))
, rand32() % 200
, rand32(1) % 250
, rand32(2) % 100
, number + 1
from numbers(1000000000);
-- 然后扩增到 32 倍
insert into test4 select * from test4;
insert into test4 select * from test4;
insert into test4 select * from test4;
insert into test4 select * from test4;
insert into test4 select * from test4;

SELECT count(*)
FROM test4

Query id: a4a01197-a22b-4a0d-9747-26555229ff58

┌─────count()─┐
│ 32000000000 │
└─────────────┘

1 row in set. Elapsed: 0.004 sec.
一共 320 亿
等后台 merge 完才 14.28 GiB 磁盘占用
楼主要的查询
WITH r AS
(
SELECT count() AS c
FROM test4
WHERE country = 100
GROUP BY uid
)
SELECT avg(c)
FROM r

Query id: c634e7a7-13fa-4d40-9f30-e6e43105ffe9

┌─avg(c)─┐
│ 32 │
└────────┘

1 row in set. Elapsed: 0.168 sec. Processed 160.30 million rows, 801.18 MB (954.12 million rows/s., 4.77 GB/s.)
0.168 秒完成

这样看起来,一年的数据单机也问题不大
注意,不同的建表语句尤其是 CODEC 非常影响存储空间和性能
220 天前
回复了 zdking08135 创建的主题 程序员 请教一个系统设计题
这个量,clickhouse 集群,做好表的设计,选好排序键、字段编码和压缩,按天分区,这个量写入和查询问题应该都不是很大。顺便,兄弟你这是在做天网么
@woodytang pg 下,如果可以用程序生成返回列然后拼接 SQL ,那么很简单
//创建测试表
create table test3("user" text,amount int,datetime timestamp);
insert into public.test3 (user, amount, datetime)
values ('A', 10, '2021-02-12 10:00:00.000000'),
('A', 20, '2021-03-12 10:00:00.000000'),
('B', 30, '2021-05-12 10:00:00.000000'),
('B', 10, '2021-06-12 10:00:00.000000'),
('C', 10, '2021-06-12 10:00:00.000000'),
('C', 20, '2021-06-12 10:00:00.000000'),
('C', 5, '2021-05-12 10:00:00.000000');
//使用 crosstab 进行 pivot
select *
from crosstab($$select "user",date_trunc('month',datetime)::date::text,sum(amount)
from test3 group by 1,2 order by 1,2 $$,
'select distinct date_trunc(''month'',datetime)::date::text from test3 order by 1') as ct(
"user" text,
"2021-02" text,
"2021-03" text,
"2021-05" text,
"2021-06" text
);
//结果
user | 2021-02 | 2021-03 | 2021-05 | 2021-06
------+---------+---------+---------+---------
A | 10 | 20 | |
B | | | 30 | 10
C | | | 5 | 30

如果要动态生成返回列名,那么确实是相当的麻烦,因为 pg 的查询必须显式制定列,只能用非常别扭的方式
-- 创建一个函数,实际查询的 SQL ,可以反复使用
create or replace function crosstabquery(_t anyelement) returns setof anyelement as
$$
declare
column_list text;
begin
select string_agg(format('%I text', d), ',')
into column_list
from (select distinct date_trunc('month', datetime)::date::text d from test3 order by 1) r;
return query execute ($b$select *
from crosstab($a$select "user",date_trunc('month',datetime)::date::text,sum(amount)
from test3 group by 1,2 order by 1,2 $a$,
'select distinct date_trunc(''month'',datetime)::date::text from test3 order by 1') as ct("user" text,$b$ ||
column_list||')' );
end ;
$$
language plpgsql;
-- 创建返回类型,每次使用前调用
do
$$
declare
column_list text;
begin
select string_agg(format('%I text', d), ',')
into column_list
from (select distinct date_trunc('month', datetime)::date::text d from test3 order by 1) r;
drop type if exists __t;
execute format('create type __t as ("user" text, %s)', column_list);
end
$$ language plpgsql;
-- 返回实际结果
select * from crosstabquery(null::__t);
user | 2021-02-01 | 2021-03-01 | 2021-05-01 | 2021-06-01
------+------------+------------+------------+------------
A | 10 | 20 | |
B | | | 30 | 10
C | | | 5 | 30
(3 rows)

不过如果可以动态生成 sql ,就别用下面这个方案,实在是别扭
这不是一句 sql 查询就能解决的事情吗,为啥要变复杂?
1  2  3  4  5  6  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   943 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 28ms · UTC 20:46 · PVG 04:46 · LAX 12:46 · JFK 15:46
Developed with CodeLauncher
♥ Do have faith in what you're doing.