广告:Codex Token 低价中转站稳定接口 · 快速接入 · 开发者备用通道
Engineering article

ClickHouse性能优化:9个索引设计指南 | 查询速度翻倍

ClickHouse性能优化:9个索引设计指南 | 查询速度翻倍 我上周刚在生产环境踩过一个索引设计的坑。项目上线前测试没问题,结果正式跑起来,查询速度比预想慢了十倍。最后发现是索引字段没选对,用了一个大字段当索引,导致查询计划完全走歪。索引不是万能的,用错了反而拖后腿。 别傻乎乎地把所有字段都加索引。我见过有人把几十个字段都加了索引,结果查询反而变慢。

ClickHouse性能优化:9个索引设计指南 | 查询速度翻倍
配图来源于网络和AI生成,仅供参考。
ClickHouse性能优化:9个索引设计指南 | 查询速度翻倍

我上周刚在生产环境踩过一个索引设计的坑。项目上线前测试没问题,结果正式跑起来,查询速度比预想慢了十倍。最后发现是索引字段没选对,用了一个大字段当索引,导致查询计划完全走歪。索引不是万能的,用错了反而拖后腿。

别傻乎乎地把所有字段都加索引。我见过有人把几十个字段都加了索引,结果查询反而变慢。这玩意儿就像数据库里的路标,用多了反而容易迷路。索引应该只加在查询频率高、过滤条件强的字段上。比如订单表,订单号和用户ID加索引,但时间戳加索引得看具体怎么用。你得先看查询语句,然后决定哪些字段真的需要索引。

我印象里有个真实案例,用户查订单状态的时候,把状态字段加了索引。结果发现高频查询的其实是订单号,所以索引该加在订单号上,而不是状态。这事儿我亲历过,别再犯同样的错误。先看查询,再决定索引。索引是工具,不是装饰品。

在ClickHouse里创建索引,记得用ALTER TABLE语句。比如ALTER TABLE orders ADD INDEX idx_order_id (order_id) TYPE minmax; 这个操作特别快,但要小心,如果你加了错误的索引,修改表结构会卡住。我之前遇到过一个表加了两个索引,结果查询计划一直卡在重新构建索引上,整个服务都瘫了。索引不是随便加的,得按需来。

索引字段类型也很重要。我之前弄过一个索引,字段是字符串类型的,结果每次查询都得做类型转换,导致性能崩了。别让索引字段类型和查询条件类型不匹配。比如用Int类型当索引,查询的时候用字符串传值,ClickHouse会自动转换,但耗时。你得确保索引字段和查询条件的类型一致,否则得不偿失。

多字段索引也得讲究顺序。我试过把订单号和用户ID都加了索引,但查询用的是用户ID,所以优化器会按照索引顺序来选。如果索引顺序反过来,查询速度就慢了。你得根据查询习惯来定索引顺序。比如经常一起用的字段,可以放在一起建复合索引。但别随便搞,得看实际查询情况。

索引的基数也得注意。如果某个字段的值几乎都一样,加索引也没用。比如一个状态字段,大部分都是“已发货”,那加索引就是浪费资源。我之前看到有人在订单表里加了状态字段索引,结果所有查询都走这个索引,反而让系统变慢。基数低的字段加索引,不仅没帮助,还增加维护成本。

索引的存储成本也得算进去。我之前把一个大表的所有字段都加了索引,结果磁盘占用翻了一倍。ClickHouse的索引虽然不占太多空间,但加多了还是会有影响。特别是像minmax这样的索引,虽然占用小,但会影响写入性能。你得权衡查询快和写入慢之间的关系,别为了快一时半会,拖垮了写入。

索引和分区要配合好。我之前遇到过一个表,分区是按日期划分的,但查询的时候用的是订单号。结果优化器在分区上过滤,反而没用到索引。这种情况下,索引和分区互不干扰,查起来反而更慢。所以得看查询条件,如果经常用分区字段,那索引可以加在分区字段上,或者配合使用。别让索引和分区互相扯皮。

有时候不是要加索引,而是要删索引。我见过一个表加了十几个索引,但实际查询大部分都不用。结果索引太多,导致写入变慢,整个系统都卡了。后来删掉几个没用的索引,查询和写入都变快了。你得定期检查索引的使用情况,删掉那些没用的。索引不是越多越好,而是越精越好。