Group By查询过慢无法使用:16M行数据求用户标记占比优化求助
问题分析与提速方案
核心问题
当前查询慢的主要原因是:仅给person建了索引,但查询需要访问qa_flag字段,数据库需要通过person索引回表读取主表的qa_flag数据,1600万条记录的回表操作会产生大量IO,导致查询超时。
具体提速方案
- 建立联合覆盖索引:创建
(person, qa_flag)联合索引,这个索引包含了查询所需的所有字段,数据库可以直接在索引中完成sum/count统计,无需回表访问主表,能把查询时间从小时级压缩到秒级甚至毫秒级。创建语句:CREATE INDEX idx_person_qaflag ON myTable(person, qa_flag); - 优化SQL逻辑:由于
qa_flag只有1和null,sum(qa_flag)等价于count(qa_flag)(count(字段)会自动忽略null值),换用count(qa_flag)写法更直观,执行效率一致。同时可以用FORMAT函数控制百分比的小数位数,避免出现过长小数:SELECT person, CONCAT(FORMAT((COUNT(qa_flag)/COUNT(*))*100, 2), '%') AS qa_ratio FROM myTable GROUP BY person; - 预计算统计结果:如果业务对数据实时性要求不高(比如允许延迟1小时/1天),可以定时将统计结果存入一个小表(如
user_qa_stats),网页直接查询这个小表即可。示例定时任务逻辑:- 创建统计表:
CREATE TABLE user_qa_stats ( person VARCHAR(50) PRIMARY KEY, -- 根据实际person字段类型调整 qa_ratio VARCHAR(20) NOT NULL ); - 定时执行更新:
REPLACE INTO user_qa_stats SELECT person, CONCAT(FORMAT((COUNT(qa_flag)/COUNT(*))*100, 2), '%') FROM myTable GROUP BY person;
SELECT * FROM user_qa_stats;,速度极快。 - 创建统计表:
- 验证执行计划:用
EXPLAIN命令查看查询的执行计划,确认是否存在全表扫描或回表操作,验证索引是否生效:EXPLAIN SELECT person, concat((sum(qa_flag)/count(*))*100, '%') FROM myTable GROUP BY person;
内容的提问来源于stack exchange,提问作者J.T.
相关产品推荐
相关产品推荐

