ClickHouse测试之mergetree中的order by字段是否符合最左原则
先简单说一下最左原则
顾名思义:
1、最左优先,以最左边的为起点任何连续的索引都能匹配上。同时遇到范围查询(>,<,between,like)就会停止匹配。
2、例如:b=2如果建立(a,b)顺序的索引,是匹配不到(a,b)索引的;
但如果查询条件是a=1 and b=2或者a=1(又或者是b=2 and b=1)就可以,因为优化器会自动调整a,b的顺序。
3、再比如a=1 and b=2 and c>3 and d=4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,因为c字段是一个范围查询,它之后的字段就会停止匹配。
测试案例如下:
表名 |
总行数 |
原始大小 |
压缩大小 |
压缩率 |
test_event_combine ORDER BY (pid, logtime)
|
355820549 |
91.19 GiB |
6.83 GiB |
7 |
test_logtime_index ORDER BY (logtime, pid) |
355820549 |
91.19 GiB |
6.85 GiB |
7 |
建表语句如下(测试数据约3.5亿条):
CREATE TABLE test.test_event_combine
|
CREATE TABLE test. test_logtime_index |
查询效率对比:
|
SELECT count(pid) AS num |
1 rows in set. Elapsed: 0.014 sec. Processed 425.98 thousand rows, 1.70 MB (30.02 million rows/s., 120.10 MB/s.) | 1 rows in set. Elapsed: 0.989 sec. Processed 355.82 million rows, 1.42 GB (359.72 million rows/s., 1.44 GB/s.) |
结论:当order by pid字段在首位的时候,比在第二个字段快了近100倍左右。
执行计划如下:
执行计划 (order by pid,logtime)
|
执行计划 (order by logtime,pid) "Plan": { |
结论:观察执行计划发现都包含索引"Keys": ["pid"],但是Selected Granules两者差异比较大;看计划即使当字段在第二位走索引了,但是还是扫描的全表数据,可以理解为索引失效。
什么是Clickhouse Projection (投影)
概念:
投影类似于物化视图,但在part-level上定义。它提供了一致性保证以及查询中的自动使用;clickhouse在21.8以上版本引入了Projection (投影) 功能,投影类似于物化视图,但在part-level上定义。
它提供了一致性保证以及查询中的自动使用, 可以将SQL查询性能提升20倍以上
特点:
ClickHouse Projection 可以看做是一种更加智能的物化视图,它有如下特点:
part-level 存储:
Projection 物化的数据就保存在原表的分区目录中,支持明细数据的普通Projection 和 预聚合Projection
无感使用,自动命中:对一张 MergeTree 可以创建多个 Projection ,当执行 Select 语句的时候,能根据查询范围,自动匹配最优的 Projection 提供查询加速。如果没有命中 Projection , 就直接查询底表。匹配规则如下:
Where 必须是 PROJECTION 定义中 GROUP BY 的子集
GROUP BY 必须是 PROJECTION 定义中 GROUP BY 的子集
SELECT 必须是 PROJECTION 定义中 SELECT 的子集
匹配多个 PROJECTION 的时候,选取读取 part 最少的
返回的数据行小于基表总数查询覆盖的分区 part 超过一半
数据同源、同生共死:因为物化的数据保存在原表的分区,所以数据的更新、合并都是同源的,也就不会出现不一致的情况了;
注意:投影是一个实验性的功能。要启用它们,必须将allow_experimental_projection_optimization设置为1
带有FINAL修饰符的SELECT语句不支持投影。
进行投影优化:
优化追加投影
set allow_experimental_projection_optimization=1; ALTER TABLE test.test_logtime_index ADD PROJECTION norm_projection8 (SELECT * ORDER BY pid); ALTER TABLE test.test_logtime_index MATERIALIZE PROJECTION norm_projection8; 1 rows in set. Elapsed: 0.057 sec. Processed 483.26 thousand rows, 1.93 MB (8.41 million rows/s., 33.63 MB/s.)g
观察执行计划:
执行计划: "Plan": { "Node Type": "Expression", "Description": "(Projection + Before ORDER BY)", "Plans": [ { "Node Type": "Aggregating", "Plans": [ { "Node Type": "Expression", "Description": "Before GROUP BY", "Plans": [ { "Node Type": "SettingQuotaAndLimits", "Description": "Set limits and quota after reading from storage", "Plans": [ { "Node Type": "ReadFromStorage", "Description": "MergeTree(with Normal projection norm_projection8)"
投影后表变化:
结论:观察执行计划,发现本次执行新增了投影"Description": "MergeTree(with Normal projection norm_projection8)"计划。增加投影后观察查询效率,比最初查询提升了近20倍左右,符合预期,但是表大小增加了一倍左右,可以看作是以空间换时间。
总结
Clickhouse的主键索引是一个稀疏索引, 它并不存储每一个行的数据, 而是存储每个子矩阵的第一个行数据, 因此8192行数据才会有一个索引值, 索引非常小, 对应的代价就是查找时, 需要用折半查找的方式来查询具体的编号, 复杂度为log(n)
主键索引可以是组合索引, 类似于mysql的组合索引, CK在查询时也必须满足最左匹配原则, 即查询时必须从最左的字段匹配起, 一旦有跳过字段方式, 索引将无法命中.
posted on 2022-10-18 16:12 RICH-ATONE 阅读(763) 评论(0) 编辑 收藏 举报