Mysql
幫助優化 MySQL 慢查詢
我正在執行一個需要一些 mysql 優化的 wordpress,我的查詢速度很慢,我想擺脫“使用臨時;使用文件排序”
詢問:
解釋 SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts 內部加入 wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) WHERE 1=1 AND ( wp_term_relationships.term_taxonomy_id IN (1,3,4,5) ) 和 wp_posts.post_type = 'post' AND(wp_posts.post_status = 'publish' 或 wp_posts.post_status = 'private') 按 wp_posts.ID 分組 由 wp_posts.post_date 訂購 DESC 限制 0, 10;
+----+-------------+-----------------------+------+--------------------------+------------------+---------+----------------+------+----------------------------------------------+ | 編號 | 選擇類型 | 表| 類型 | 可能的鍵 | 關鍵 | key_len | 參考 | 行 | 額外 | +----+-------------+-----------------------+------+--------------------------+------------------+---------+----------------+------+----------------------------------------------+ | 1 | 簡單 | wp_posts | 參考 | PRIMARY,type_status_date | type_status_date | 62 | 常量 | 4 | 使用哪裡;使用臨時的;使用文件排序 | | 1 | 簡單 | wp_term_relationships | 參考 | PRIMARY,term_taxonomy_id | 初級 | 8 | wp.wp_posts.ID | 1 | 使用哪裡;使用索引 | +----+-------------+-----------------------+------+--------------------------+------------------+---------+----------------+------+----------------------------------------------+
我已經上傳了 2 個測試表(4 個類別和 10 個文章)的轉儲文件
我已經嘗試了很多東西但沒有任何效果,嘗試添加索引並強制它們,嘗試使用子查詢等等,從我看到的主要問題是連接行和 post_date 的順序,mysql 不能使用 type_status_date 索引進行排序,因為日期列不是“最左邊的列”,已經有一個未使用的 post_date 索引,即使我重新排序 type_status_date 中的列,這也無濟於事
謝謝
我想擺脫“使用臨時;使用文件排序”
我看到的問題之一是您使用了不同的
GROUP BY
andORDER BY
子句。從關於 MySQL 如何使用臨時表的手冊中:如果存在 ORDER BY 子句和不同的 GROUP BY 子句,或者如果 ORDER BY 或 GROUP BY 包含來自連接隊列中第一個表以外的表的列,則會創建一個臨時表。
一旦您創建了一個臨時表,就需要根據您的
ORDER BY
子句對其進行排序,由“使用文件排序”指示。這個執行計劃至少使用索引來適當地限制找到的行數。
我還會查看有關 ORDER BY 優化的文件。
首先,我將創建以下索引:
ALTER TABLE `wp_posts` ADD INDEX `wp_posts_idx_type_date` (`post_type`, `post_date`); ALTER TABLE `wp_posts` ADD INDEX `wp_posts_idx_date` (`post_date`); ALTER TABLE `wp_posts` ADD INDEX `wp_posts_idx_id` (`ID`); ALTER TABLE `wp_term_relationships` ADD INDEX `wp_term_relationship_idx_id` (`object_id`);
關於查詢更改的一些建議:
- 避免 SQL_CALC_FOUND_ROWS - 嘗試在 2 個單獨的查詢中執行 COUNT 和查詢本身。在許多情況下,這可能更有效。
- 將連接替換為
wp_term_relationship
可以替換為 EXISTS。當連接表在任何地方都沒有使用時,除非在 WHERE 子句中,它可以替換為 EXISTS 子查詢,以避免 GROUP BY 子句的冗餘分組。在這種情況下,您可以刪除 GROUP BY。- 用 IN 替換 OR 條件(並不是真正的性能提升,但它更具可讀性)。
應用了這些建議和其他一些小改動:
SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts WHERE 1 = 1 AND ( 1 = 1 ) AND wp_posts.post_type = 'post' AND ( wp_posts.post_status IN ( 'publish', 'private' ) ) AND EXISTS ( SELECT * FROM wp_term_relationships WHERE ( wp_posts.ID = wp_term_relationships.object_id ) AND wp_term_relationships.term_taxonomy_id IN ( 1, 3, 4, 5 ) ) ORDER BY wp_posts.post_date DESC LIMIT 0, 10