SELECT post.* FROM post INNER JOIN post_tag ON post.id = post_tag.post_id WHERE post.status = 1 AND post_tag.tag_id = 123 ORDER BY post.created DESC LIMIT 100;
| 方案 | 驅動表 | Key | Rows | Extra |
|---|---|---|---|---|
| 原始 | post_tag | tag_id | 71,220 | Using where; Using filesort |
| STRAIGHT_JOIN | post | status_created | 119,340 | Using where |
優化器預設「結果集小的表做驅動表」。post_tag.tag_id=123 過濾後 7 萬行 < post.status=1 12 萬行,故選 post_tag 驅動。但 ORDER BY post.created 排序欄位不在驅動表,觸發 filesort。
SELECT post.* FROM post STRAIGHT_JOIN post_tag ON post.id = post_tag.post_id WHERE post.status = 1 AND post_tag.tag_id = 123 ORDER BY post.created DESC LIMIT 100;
強制以 post 為驅動表,利用 status_created 索引同時完成過濾與排序,避免 filesort。
ALTER TABLE post ADD INDEX status_created (status, created DESC);ANALYZE TABLE post, post_tag;