You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何加速千万级bugs表按token、reported_at查title的SELECT SQL速度

问题根因分析

你的查询执行慢主要有三个核心原因:

  • 现有索引设计不符合当前查询的最左前缀匹配规则,过滤效率极低:你目前的联合索引为(category, token, reported_at),但查询条件没有传入category字段,数据库无法利用这个索引快速定位token和reported_at匹配的记录。你看到的“查询用到索引”实际是全索引扫描,扫描行数远高于实际符合条件的行数。
  • 存在回表开销:即使数据库通过索引定位到了符合条件的记录id,现有索引不包含你需要查询的title字段,必须回到主键索引逐行读取title数据,大量随机IO会严重拖慢查询速度。
  • 查询写法存在冗余和逻辑问题:你当前写的嵌套子查询没有实际意义,子查询结果集仅包含id字段,外层直接查询title既没有关联条件也没有对应字段,不仅会增加优化器解析成本,甚至可能触发不符合预期的笛卡尔积或语法报错。
优化方案

按照优先级从高到低执行即可:

1. 先修正SQL写法

去掉无意义的嵌套子查询,直接写单表查询即可,减少不必要的开销:

SELECT title FROM bugs WHERE reported_at = '2020-08-30' AND token = 'token660';

如果确实需要通过子查询过滤id,必须加上id关联条件,比如:

SELECT b.title 
FROM bugs b
INNER JOIN (
    SELECT id FROM bugs WHERE reported_at = '2020-08-30' AND token = 'token660'
) t ON b.id = t.id;

但这种写法相比直接单表查询没有任何收益,不推荐使用。

2. 创建适配查询场景的覆盖索引(核心优化)

直接创建包含过滤条件和返回字段的联合覆盖索引,让查询可以直接从索引中拿到所有需要的数据,完全避免回表:

CREATE INDEX idx_bugs_token_reportedat_title ON bugs(token, reported_at, title);

索引设计逻辑:

  • 将两个等值查询的过滤列token、reported_at放在索引最前列,数据库可以通过索引直接定位到所有符合条件的记录,扫描范围极小
  • 把需要返回的title列放在索引末尾,整个查询不需要访问主键表数据,索引扫描即可完成所有逻辑,随机IO转为顺序IO,在千万级表上性能通常可以提升10~100倍。

如果你的业务中大量查询都会同时带上category过滤条件,也可以将索引调整为(token, reported_at, category, title),不会影响当前查询的效率,同时可以兼容更多查询场景。新索引创建完成后,如果没有其他查询强依赖旧的(category, token, reported_at)索引,建议删除旧索引,减少写入时的索引维护开销。

3. 辅助优化项

  • 确认reported_at字段为DATE/DATETIME类型,不要用字符串存储时间,避免隐式类型转换导致索引失效
  • 如果单条件过滤后的结果集超过1万条,加上LIMIT分页读取,不要一次性拉取全量数据,减少扫描和网络传输开销
  • 索引创建完成后执行ANALYZE TABLE bugs;更新表统计信息,避免优化器因为统计信息不准选错执行计划

内容的提问来源于stack exchange,提问作者AYehia0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 01:21:47