继这个帖子(https://ruby-china.org/topics/32552)中提到的坑之后,今天又遇到了一个经典的 MySQL 坑 mysql slow order by with limit
代码里的原始查询,这个查询查出来 6 个结果,耗时 1000ms。
SELECT merge_requests.*
FROM merge_requests
WHERE
merge_requests.state IN ('opened','reopened') AND
merge_requests.target_project_id = 32100
ORDER BY
created_at DESC id DESC LIMIT 15 OFFSET 0;
按照 https://explainextended.com/2011/02/11/late-row-lookups-innodb/ 的介绍改写,耗时 500ms,还是好久。。
SELECT m.*
FROM (
SELECT id
FROM merge_requests
WHERE
state IN ('opened','reopened') AND
target_project_id = 32100
ORDER BY created_at DESC
LIMIT 15
) q
JOIN merge_requests m
ON m.id = q.id
ORDER by m.id;
如果把 LIMIT
改成 6 或者 6 以下,耗时 10ms!;如果把 where 中的条件去掉一个,耗时也是 10ms!...还没找到比较好的写法。。
gitlab 的各种分页很容易有这种查询,自己部署 gitlab 慎用 MySQL...不过大概搜了一下,好像 PG 也有这种问题,还是要优化查询语句啊。。。