问题描述:

SQL 慢查询,在我们给 x 度做输出抓取的时候,需要扫描全部的帖子,把帖子数据生成固定的格式(XML 文件)让 x 度来抓取。目前 DBA 那边有一个慢查询,大约每天 5000 次执行,查询语句如下:

select * from `jz_post` where `id` > '{x}' and (`st` = '5') order by `id` asc limit 500

这个语句的目的就是取固定状态下所有的帖子,按照 id 分批取,id 是主键,st 也有索引。该语句从 Explain 上看,是使用到索引了,但是 order by 引起性能问题,我们是循环批量取数据,为了保证数据的完整不被遗漏,所以需要 order by,Explain 如下图所示:

Explain

这个查询语句虽然用了索引,但是速度还是会非常慢,因为总体数据量大,id 和 st 都是有索引的,如果只是通过 id 和 st 索引,根本解决不了问题,采取的优化手段就是拆分查询,将获取数据分为两部分:

  • select id from jz_post where id > ‘{x}’ and st = 5 order by id asc limit 500;
  • select * from jz_post where id in (‘上一次查询 ID 的结果’)

看下 Explain 结果:

Explain

从影响的数据行上来看第一次查询 id 已经不存在性能问题了,一定量的 id 取数据也不会有性能问题,带来的后果就是程序里需要单独去再次查询结果集,但是不会影响整个数据库。

EOF;