WordPress媒体库数据量多了,创建提速查询RAR PDF MP4 文档等数据类型的索引
由于WordPress上传图片和附件时直接保存在post表里的,所以这个表数据越来越多,为了稍微快一点点,对于除了图片以外的其他附件,建议建立联合索引。
图片走原生索引,其他附件走新的联合索引,降低数据库压力。
索引A:
ALTER TABLE wp_posts ADD INDEX `idx_im2828_mime_date` (`post_mime_type`(100), `post_date` DESC, `ID`);
索引B:
ALTER TABLE wp_posts ADD INDEX `idx_im2828_type_mime_date`(`post_type`,`post_status`,`post_mime_type`(100),`post_date` DESC,`ID`);
索引A和索引B只能二选一,建议使用A,更轻量。
两者区别讲解:
## 最左前缀匹配差异
### A:`post_mime_type`放第一位
✅可命中:
- `post_mime_type='xxx'`
- `post_mime_type LIKE 'video/%'`
❌**不能跳过 mime 直接用后面字段**:
>
> 如果 where 不带 post_mime_type 条件,这个索引完全用不上。
### B:`post_type,post_status`放最前面
✅可命中:
1. `post_type + post_status`(不带 mime 条件也能用)
2. `post_type + post_status + post_mime_type`(我们媒体库查询)
3. `post_type + post_status + post_mime_type + order by post_date desc`
B 的适用查询场景更多。
## 2. 针对我们的 SQL:
WHERE post_type='attachment' AND post_status='inherit' AND post_mime_type LIKE 'image/%' ORDER BY post_date DESC LIMIT 20
- **索引 A**:索引第一列是 mime。MySQL 需要先找出全部 image/% 记录,再做排序。图片数量巨大时,优化器认为开销大,放弃 A,改用`type_status_date`。
- **索引 B**:最左两列直接过滤`post_type='attachment' AND post_status='inherit'`,紧接着过滤 mime,索引内部已经按`post_date DESC`排好序。理论上整条 where+order by 全部可以在索引完成。
>
> 即便 B,当 image 占比极高,MySQL 依然有可能选择原生`type_status_date`,因为原生索引字段更少,体积更小。
## 3. 索引体积 & 写入开销(重点)
- A:3 列 `post_mime_type(100)+post_date+ID`,体积小,写入压力小。
- B:5 列 `post_type+post_status+post_mime_type(100)+post_date+ID`,字段更多,**索引更大,INSERT / UPDATE / DELETE 成本更高**。
wp_posts 每新增 / 修改一行,就要维护这个索引,写多的站点会有可感知损耗。
也就是说:真正高频的编辑器场景不受这个问题影响;只有后台媒体总列表筛选图片才触发这条 SQL。
最后执行查询EXPLAIN 观察:
EXPLAIN SELECT * FROM wp_posts WHERE post_type='attachment' AND post_status='inherit' AND post_mime_type LIKE 'image/%' ORDER BY post_date DESC LIMIT 20;
理想:`key`使用`idx_im2828_mime_date`,无 filesort。
