在查询 clickhouse 时,当同时使用 limit 和 order by 时,如果 order by 的顺序与表顺序一致, 则可以加速查询。
但是 optimize_read_in_order 在某些情况下会导致性能裂化。
建表语句:
create table test (
`a` string,
b `string`,
d `string`,
index_d)
ENGINE = MergeTree order by (a, b)
使用普通磁盘测试, ssd 太快了测不出来,冷热分离的时候就有坑了。
optimize_read_in_order 加速的查询
按前缀主键排序:
order by prefix primary key
查询语句:
select * from test order by a limit 1
倒序逆序无影响。
optimize_read_in_order 可能无效的情况
按部分主键过滤并按剩余主键排序:
filter with prefix primary key and order by suffix primary key
查询语句:
select * from test where a = ? order by b limit 1
当 clickhouse 版本较低(21.8.3, 阿里云最新 clickhouse)时无效, 最新版 clickhouse 有效。
前缀主键和后缀主键加起来必须构成完整的主键,
optimize_read_in_order 劣化的查询
当查询条件上有索引时: github.com/ClickHouse/…
select * from test where d = ? order by a limit 1
- optimize_read_in_order = true。 sql 会先读取数据,然后再进行过滤,这个过程不会使用 d 的索引。
- optimize_read_in_order = false。sql 会首先使用 d 的索引过滤出所有符合条件的数据,然后再排序。
一些奇怪的情况
即使是最简单的查询, 如果排序键的顺序与主键顺序不一致,也有可能导致劣化: github.com/ClickHouse/…
select * from test where b = ? order by a desc limit 1
这种情况下,建议修改表主键排序顺序:
create table test (
`a` string,
b `string`,
d `string`,
index_d)
ENGINE = MergeTree order by (-a, b)
然后使用 -a asc 的方式,来达到 a desc 的排序。
select * from test where b = ? order by -a limit 1