列式数据库 clickhouse 单机能处理十几亿数据吗

2021-03-17 22:55:53 +08:00
 Leviathann

有个需求要优化查询 A 表有 18 亿数据,大概每天千万条,每个数据都有 app_id , shop_iddate ,然后是 order by date

B 表则是每个 app_id 一天一条数据,每条数据有一个存了符合某种情况的 shop_idbitmap

现在要查满足某种情况的 shop 在 A 表里的数据,limit 100000

试了下

select * from A inner join B on A.app_id = B.app_id and A.date = B.date 
where app_id = 1 
and date between '2021-03-10' and '2021-03-16'
and bitmapContains(B.bitmap, A.shop_id) 
limit 10;

这样完全都跑不动,报内存不够了,昨天的数据也就千万级左右,用子查询先把 B 表用 date 过滤一下再 join 也没用

我猜想 clickhouse 是先全 join 起来再用 where 过滤

查了下文档发现能构造 map,感觉可以用 B 表构造一个 date-bitmap 的 map 然后直接 where 就行

但是直接复制文档上的构造 map 的 sql 都报语法错误,好像是我这个版本根本不支持 map

还有其他好办法吗

1994 次点击
所在节点    数据库
17 条回复
zzn
2021-03-17 22:59:01 +08:00
`select * `?
要获取 100000 条裸数据的意思?
Leviathann
2021-03-17 23:22:09 +08:00
@zzn
是的
差不多就是 select * ,因为主要内容就一个长度在 2 、30 左右的字符串,其他的都是相关信息,基本都是 uint8 、时间啥的,包括上面提到的一共就 9 列
wmhack
2021-03-17 23:49:13 +08:00
用 clickhouse 就对了,我们目前单表 20 多亿,秒查结果
zzn
2021-03-17 23:51:02 +08:00
可以试试把更多过滤条件放到 ON (不确定行不行,clickhouse join 一向挺弱的)

不过,这东西的典型场景是 OLAP,鼓励宽表(冗余数据),少 join
ericls
2021-03-18 06:45:46 +08:00
@zzn exactly!
liprais
2021-03-18 08:01:58 +08:00
有 date 为啥不用 partition
echo1937
2021-03-18 08:31:11 +08:00
我们也在使用 clickhouse,刚起步,楼主要不起个群我们一起交流交流
aec4d
2021-03-18 09:11:23 +08:00
虽然它能连表,但是一般连表性能降低挺厉害,最好是组成大宽表,另外特别注意分区键,如果匹配不上分区键基本就是全表扫描,速度会降低很多,不是说大家都说它牛逼它就无所不能,使用前最好还是思考一下为什么快,又不是魔法
kerro1990
2021-03-18 09:19:36 +08:00
clickhouse 单表 70 亿,查询在毫秒级响应
Leviathann
2021-03-18 09:33:36 +08:00
@liprais
@aec4d
说实话我没搞懂这个 partition 和 order by 之间的关系
是数据按照 partition 分文件,然后文件内部用 order by 排序并按照粒度做了一个索引,如果查询的东西不再某个颗粒的索引范围就直接跳过这个颗粒包含的数据?
这个 A 表是用 app_id, toYYYYMM(date)...
winnie2012
2021-03-18 10:28:48 +08:00
仔细审了下题,这个需求跟 B 表没关系,为啥要关联 B
kssdxw
2021-03-18 10:59:59 +08:00
引擎看看用的是不是 mergetree,记得设置 PARTITION BY,join 最好先 where 再 join,尽量小表 join 大表不然很慢
Leviathann
2021-03-18 11:21:36 +08:00
@kssdxw
A 是 replace merge tree
B 是 aggregating merge tree

我先用子查询把 A 限制到 10000 行,把 B 表 限制到 1 行,然后再 join B 表,
最外面的 select 只选 A 表的 app_id date 和一个字符串字段(长度 2 、30 左右)
结果都要 6.7 秒

join B 表的时候是结果有多少条就会把 B 表的 bitmap 复制多少次吗...这个 bitmap 的基数大概是几十万
Leviathann
2021-03-18 11:26:17 +08:00
@winnie2012 需要满足同 app_id+date 时,A 表的 shop_id 包含在 B 表 shop_id_bitmap 里...
rapperx2
2021-03-18 16:21:04 +08:00
目前 15 亿 稳稳的秒查
kele1997
2021-03-18 18:30:06 +08:00
你可以试试先用上面的查询查出 A 表的主键,然后使用 select * from A where A.id in {.......} ,估计会占内存少一些
Leviathann
2021-03-20 15:55:11 +08:00
之前有一个想法,把 B 表的 bitmap 聚合成一个 map,以 date 为 key,shop_id_bitmap 为 value,这样把表的维度压缩成 0 就能直接写在 where 条件里过滤 A 表的记录,但是翻了下文档好像并不支持这种用法,map 的 value 只支持几个简单的数据类型
最后还是决定加字段了
clickhouse 的单表 where 还是超级强力的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/762634

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX