背景:
有几条类似的sql 语句查询同一个表,这个表数据量在100w-300w 之间,sql语句select xxx from xx
where a = xx group by xxx ,其中a字段索引选择性差,现在在tiflash 这边跑 ,一分钟跑几十条,导致tiflash cpu 打爆了,去tikv 那边,并发查询太多了,也怕把tikv cpu 打爆,应用那边对这条sql 也没法 好优化的方式,求助,目前有什么好的解决方式吗
执行计划方面有异常吗?从group by来看肯定是要走排序和本地计算的吧
SQL也很简单,要是都没发调整,就看看group 操作是否能提前计算历史的,然后累积新数据的group,类似数仓的设计思想。
老师,能详细说说吗
一般高频sql就不太适合添加为tiflash
高并发,字段索引选择度低,并且需要group by 。相对tiflash更适合
选型:
高并发点查 → TiKV
聚合 / 分组 / 低选择性过滤 → TiFlash
建议使用tiflash 但是做资源管控。限制并发。
可以优化下索引 比如覆盖索引
如果只使用tidb的话,就是搞一个宽表吧,或者如果表里有类似时间的字段,将当日之前的数据先group了,最后实时跑的时候,就是计算的结果,sum上,今日的数据的group,如果数据不能区分估计就不能这样搞。
要不就增加tiflash节点试试。
利用覆盖索引,让 TiFlash 少扫数据,看看能否解决
在 TiDB 层面,可以通过设置 performance.max-procs来限制 TiDB 服务器上同时处理的 goroutine 数量,间接控制并发查询数
高频AP查询打爆TiFlash CPU。建议强制绑定TiKV引擎分流,或用资源管控对TiFlash限流,避免资源争用。
给表建 (a, 分组字段) 覆盖复合索引,用资源组限流报表 SQL,隔离 TiFlash/TiKV 负载。
过滤字段a选择性极差(等值过滤后仍返回大量行,索引无裁剪效果)
条件字段 a 基数极低(选择性差),TiFlash 没有二级索引,每一条 SQL 都触发整表列存全扫描 + 内存 Hash 分组;
一分钟几十条并发,每条都扫 100w~300w 行,大量 CPU 消耗在扫描 + 哈希聚合,直接打满 TiFlash;
切回 TiKV 又面临并发索引扫描 + 回表,高并发下极易把 TiKV CPU 打穿;
应用无法改 SQL 逻辑,只能在数据库侧做限流、分流、预聚合、缓存。
根因是 a 字段选择性差 + 高并发,走 TiKV 索引扫描效率低(选择性差索引等于扫大量行),走 TiFlash 又因为每条都要列扫聚合、几十条并发直接把 CPU 打满。100w-300w 这个量级其实不大,几个方向:1)资源隔离优先——用 Resource Control 给这类查询单独建 resource group 并限流(RU 上限),避免它们把 TiFlash/TiKV 打爆影响其他业务,这是最快见效的止血手段;2)既然 a 选择性差,单纯 group by 聚合可以考虑加合适的组合索引让 TiKV 侧能覆盖扫描,或者评估这类聚合能否走 TiFlash 但降低并发(应用侧加并发控制/排队);3)如果这几条 SQL 结果时效性要求不高,考虑用物化的方式:定期把聚合结果算好存到一张结果表,查询直接读结果表,把实时聚合改成预计算;4)确认是否可以用 MPP 但限制 tiflash 的线程数(tidb_max_tiflash_threads 等)避免单查询吃满 CPU。综合看,先用 resource group 限流止血,再从预聚合或索引层面根治。