Mysql

幫助優化 MySQL 慢查詢

  • March 21, 2018

我正在執行一個需要一些 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 個文章)的轉儲文件

http://pastebin.com/6zhVGQH7

http://pastebin.com/vUnkKqtP

我已經嘗試了很多東西但沒有任何效果,嘗試添加索引並強制它們,嘗試使用子查詢等等,從我看到的主要問題是連接行和 post_date 的順序,mysql 不能使用 type_status_date 索引進行排序,因為日期列不是“最左邊的列”,已經有一個未使用的 post_date 索引,即使我重新排序 type_status_date 中的列,這也無濟於事

謝謝

我想擺脫“使用臨時;使用文件排序”

我看到的問題之一是您使用了不同的GROUP BYandORDER 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`);

關於查詢更改的一些建議:

  1. 避免 SQL_CALC_FOUND_ROWS - 嘗試在 2 個單獨的查詢中執行 COUNT 和查詢本身。在許多情況下,這可能更有效。
  2. 將連接替換為wp_term_relationship可以替換為 EXISTS。當連接表在任何地方都沒有使用時,除非在 WHERE 子句中,它可以替換為 EXISTS 子查詢,以避免 GROUP BY 子句的冗餘分組。在這種情況下,您可以刪除 GROUP BY。
  3. 用 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

引用自:https://dba.stackexchange.com/questions/7682