2016-03-28 80 views
0

據我所知,以下查詢不是太複雜,但它仍然需要3秒以上。 關於如何優化這個的任何想法?關於優化MySQL查詢:簡單的MySQL查詢需要3秒以上

SELECT 
    wpp.ID, wpp.post_title, wpp.post_author, 
    wpp.post_status, s.supplier_company 
FROM wp_posts AS wpp 
LEFT JOIN wp_postmeta AS postmeta ON wpp.ID = postmeta.post_id 
LEFT JOIN wp_term_relationships AS term_link ON wpp.ID = term_link.object_id 
LEFT JOIN wp_terms AS terms ON term_link.term_taxonomy_id = terms.term_id 
LEFT JOIN wp_teleapo_supplier AS s ON wpp.post_author = s.ID 
WHERE wpp.post_type = 'post' 
AND wpp.post_warning <> 'no_image' 
AND wpp.post_status <> 'trash' 
AND wpp.post_status <> 'auto-draft' 
GROUP BY wpp.ID 
ORDER BY post_date DESC 
LIMIT 100 OFFSET 0 

現在我所有的餐桌都有大約2000〜9000個職位。
1)在wp_posts中有15000個記錄,但只有大約3000個,使用WHERE wpp.post_type = 'post'
2)圍繞9000在wp_term_relationships
但很容易在不久的將來成長......

問題的起源:

在上面的短查詢,如果我改變:

GROUP BY wpp.ID 
ORDER BY post_date DESC 

TO

GROUP BY wpp.ID 
ORDER BY wpp.ID DESC 

我的查詢時間從3.3秒到0.3秒...但是我想要一個方法,所以我仍然可以ORDER BY post_date

東西是更加古怪的是,樓下全搜索查詢會在不到1秒,即使GROUP和ORDER BY的是不同的...

解釋短期查詢結果:

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE wpp ref type_status_date,post_type,post_status post_type 62 const 3351 Using where; Using temporary; Using filesort 
1 SIMPLE postmeta ref post_id post_id 8 r_11524_jtc.wpp.ID 7 Using index 
1 SIMPLE term_link ref PRIMARY PRIMARY 8 r_11524_jtc.wpp.ID 92 Using index 
1 SIMPLE terms eq_ref PRIMARY PRIMARY 8 r_11524_jtc.term_link.term_taxonomy_id 1 Using index 
1 SIMPLE s eq_ref ID ID 4 r_11524_jtc.wpp.post_author 1 

這些都是我的指標:

enter image description here

全搜索根據用戶羯羊或不填,他在某些搜索領域中,最奇怪的是,即使ORDER BY列與GROUP BY列不同,以下搜索查詢僅需要0.3秒!

SELECT SQL_CALC_FOUND_ROWS wpp.ID, wpp.post_title, wpp.post_author, 
     wpp.post_status, s.supplier_company, 
     GROUP_CONCAT(DISTINCT terms.slug SEPARATOR ',') AS allslug, 
     GROUP_CONCAT(DISTINCT terms.name SEPARATOR ',') AS allcatname 
    FROM wp_posts AS wpp 
    LEFT JOIN wp_postmeta AS postmeta ON wpp.ID = postmeta.post_id 
    LEFT JOIN wp_term_relationships AS term_link ON wpp.ID = term_link.object_id 
    LEFT JOIN wp_terms AS terms ON term_link.term_taxonomy_id = terms.term_id 
    LEFT JOIN wp_teleapo_supplier AS s ON wpp.post_author = s.ID 
    WHERE wpp.post_type = 'post' 
     AND wpp.post_warning <> 'no_image' 
     AND wpp.post_status <> 'trash' 
     AND wpp.post_status <> 'auto-draft' /* All search on post_title 
     and any postmeta value */ 
     AND (post_title LIKE '%textile%' 
     OR postmeta.meta_value LIKE '%textile%') 
       /* extra filters. The one below is an example of a filter on 
       the user #324 but this field can also take the username 
       (supplier_company) parameters etc. */ 
     AND (wpp.post_author LIKE '%324%' 
       OR (EXISTS 
         (SELECT 1 
          FROM wp_teleapo_supplier as s2 
          WHERE s2.ID = wpp.post_author 
           AND (s2.supplier_company  LIKE '%324%' 
           OR s2.supplier_company_kana LIKE '%324%'))) 
       OR (EXISTS 
         (SELECT 1 
          FROM wp_postmeta AS postmeta2 
          WHERE postmeta2.post_id = wpp.ID 
           AND postmeta2.meta_key = 'input_comp' 
           AND postmeta2.meta_value LIKE '%324%'))) 
    GROUP BY wpp.ID /* Filter on Categories!! */ 
    HAVING (allcatname LIKE '%apparel-and-accessories%' 
      OR allslug LIKE '%apparel-and-accessories%') 
    ORDER BY post_date DESC 
    LIMIT 20 OFFSET 0 
+0

桌子有多大?你有什麼指數? –

+0

親愛的@ PM77-1謝謝!我用索引和表格大小更新了這個問題。 – mesqueeb

+0

當你通過[Explain](http://dev.mysql.com/doc/refman/5.7/en/explain.html)運行查詢時會發生什麼? – Drew

回答

0

理念的

潛在的問題:如果沒有GROUP BY,你有沒有看到一個wpp.ID多個supplier_company值?如果是這樣,你想要哪一個?或者你想要GROUP_CONCAT(s.supplier_company)

理念乙

你想NULL出來爲supplier_company?如果是這樣,你可能會被這個緩慢的查詢卡住。 (和WP鼓勵的怪EAV架構設計。)

如果你寧願跳過NULLs,然後擺脫所有的LEFTs。使用LEFT,查詢正在收集各種NULL,只是爲了最終拋棄它們。

思想Ç

此外,沒有LEFTs,有可能通過以相反的順序的錶行走。也就是說,從wp_teleapo_supplier開始,看看哪些帖子彈出。 (有可能需要一些更多的索引,以遵循的順序表。)

理念d

如果不需要GROUP BY,將其刪除,並與INDEX(post_type, post_date)取代INDEX(post_type)。這樣,可能能夠使用索引停止時,只有100行已被找到。或者是post_date不在wpp ??? 合格所有列JOINing

其他

一些評論暗示你離開了一些信息。在這種情況下,我的建議可能毫無用處。請不要'簡化'查詢。

s has no PRIMARY KEY?這是一個禁忌。請提供SHOW CREATE TABLE wp_teleapo_supplier,以便我們可以討論PK應該是什麼。

更長的查詢

一些性能殺手在較長的查詢

  • LIKE '%...'出現 - 不能使用索引
  • OR - 不能使用索引。一種解決方法是將查詢重新配置爲UNION,但考慮到多個ORs,這將是一場噩夢。
  • GROUP BYORDER BY在不同的列上。即使他們在同一列上,在這個查詢中發生的事情也會太多,以獲得更多好處。
  • OFFSET聞起來像「分頁」。
  • SQL_CALC_FOUND_ROWS - 查詢必須完成查找所有內容。由於LIMIT不能用索引來完成,所以沒關係。

我能想到的唯一希望就是重新設計架構和用戶界面,以便在搜索時進行搜索。該查詢不會有顯着的加速。

+0

早安瑞克! ** A)**這些帖子總是在供應商表中鏈接0或1條記錄,因此不需要group_concat。 ** B)**當沒有供應商數據時,可以取NULL。 ** C)**搜索函數檢索帖子,當用戶搜索某些東西時,mysql查詢變得更大。例如過濾供應商/過濾器上的帖子等等,這就是爲什麼我認爲我需要從'wp_posts'表開始。我的GROUP BY的原因是因爲我需要能夠過濾類別。 – mesqueeb

+0

只要我不能解決更好的方法來過濾類別,我需要'GROUP_CONCAT' +'HAVING' +'GROUP BY'方式來過濾我的帖子。我的問題在這裏描述:http://stackoverflow.com/questions/36246152/using-mysql-exists-with-double-left-join-using-a-join-table – mesqueeb

+0

'wp_teleapo_supplier'確實沒有主鍵。我現在將它添加到'ID'列! – mesqueeb