2013-07-02 46 views
3

我試圖通過向查詢出現在慢查詢日誌中添加索引來改善錘打WordPress數據庫的性能。你如何在MySQL中強制查詢使用索引?

在MS SQL,您可以使用查詢提示強制查詢使用索引,但它通常是很容易獲得的查詢,如果你正確等覆蓋列

我有這樣的查詢使用索引出現在慢查詢日誌很多

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID 
FROM wp_posts 
WHERE 1=1 
    AND wp_posts.post_type = 'post' 
    AND (wp_posts.post_status = 'publish') 
ORDER BY wp_posts.post_date DESC 
    LIMIT 18310, 5; 

我創建了wp_posts覆蓋唯一索引post_date, post_status, post_type and post_id並重新啓動MySQL的但是當我運行解釋使用的指標是

status_password_id 

,並在可能的密鑰我的新指數甚至沒有出現,雖然這是一個覆蓋索引例如我剛剛得到

type_status_date,status_password_id 

因此無論是使用索引或可能的選擇「優化器」,如果MySQL有一個是甚至考慮以post_date作爲第一列的索引。我本來以爲一個查詢,基本上是做日期頂部和排序與

ORDER BY wp_posts.post_date DESC LIMIT 18310, 5; 

會希望使用日期速率大小的指標,特別是那種把所有滿足查詢所需的其他領域它呢?

MySQL是否提供查詢提示來強制索引用於速度/性能測試,或者是否有其他事情我需要做,以瞭解爲什麼忽略此索引。

我很喜歡它,如果Navicat有一個像MS SQL的可視化查詢執行計劃,但它似乎是EXPLAIN是它提供的最好的。

任何人有任何提示我如何強制索引被使用或解決爲什麼被忽略將是非常有益的!

感謝

+1

你可以嘗試改變你的索引def wp_posts到'post_type,post_status,post_date,post_id'的順序 –

+0

@IanKenney你應該發佈這個答案。這個索引將被使用(不需要提示),並且查詢將盡可能高效(考慮到相當大的偏移量)。 –

回答

1

試着改變你的索引定義的順序,以

post_type, post_status, post_date, post_id 

post_date desc, post_type, post_status, post_id 
+0

我已經有了該鍵順序的索引。 –

+0

您可以向我解釋(如果可能)我如何在Navicat(或任何其他工具)中看到類似於MS SQL Query Optimiser的東西,以便我可以看到有關爲什麼選擇一個索引的更多細節。由於大量行的排序和日期限制,我會認爲我的索引的順序會更合適。 MySQL是否像非常舊的MS SQL版本,其中沒有查詢優化器,您必須按照最具選擇性的順序排列where子句?還是有優化器? –

+0

即使是對非日期列沒有選擇性的查詢,例如它們剛剛出現在select中,也不是使用查詢,而是使用基本的post_date索引,例如解釋從wp_posts中選擇id,post_type,post_status order by post_date desc limit 20, 5我會想到一個帶post_date的覆蓋索引作爲第一個鍵對於這個排序結果是理想的,然後其他鍵保存select的值 –

9

用MySQL有查詢提示強制索引用於速度/性能測試還是還有其他事情我需要做,以瞭解爲什麼該索引被忽略。

The documentation答案在一些細節這個問題:

通過指定USE INDEX(index_list),你可以告訴MySQL使用 只有指定的指標之一查找表中的行。 替代語法IGNORE INDEX(index_list)可以用來告訴 MySQL不使用某些特定的索引或索引。如果EXPLAIN顯示MySQL正在使用可能索引列表中的錯誤索引 ,則這些提示爲 有用。

您還可以使用FORCE INDEX,這就像USE INDEX(index_list) 但與另外一個表掃描被假設爲非常昂貴 。換句話說,只有在沒有 方式使用某個給定索引在表中查找行時才使用表掃描。

每個提示都需要索引的名稱,而不是列的名稱。 PRIMARY KEY的 的名稱是PRIMARY。要查看 表的索引名稱,請使用SHOW INDEX

如果USE INDEX不行,請嘗試使用IGNORE INDEX,查看優化的第二選擇是什麼(或第三個,依此類推)。

語法的一個簡單的例子是:

SELECT * FROM t1 USE INDEX (i1) IGNORE INDEX (i2) WHERE ... 

有許多地方從,在鏈接的文檔來更多。我已鏈接到5.0版本的頁面,但您可以使用左側邊欄輕鬆導航到適當的版本;從版本5.1開始,還有一些額外的語法選項可用。

6

MySQL 5.6支持新的格式的EXPLAIN,其中MySQL Workbench GUI可以以更吸引人的方式形象化。但是如果你被困在MySQL 5.5或更早的版本上,那對你來說並沒有什麼幫助。

MySQL確實提示@AirThomas提到,但你應該真的很謹慎地使用它們。在一個簡單的查詢中,如你所顯示的那樣,如果你有正確的索引,就不需要使用索引提示。使用索引提示意味着你的應用程序有硬編碼的索引名稱,所以如果你添加或刪除索引,你必須更新你的代碼。

在您的查詢中,(post_date, post_status, post_type, post_id)上的索引不起作用。

您希望索引中最左邊的列用於行限制。所以先把post_status, post_type。最好,如果選擇性更高的列是第一。也就是說,如果post_type = 'post'與表格的3%相匹配,並且post_status = 'publish'與表格的1%相匹配,則post_type之前先放置post_status。

由於您對條件和AND運算符都使用了=,因此您知道所有匹配行基本上都與這兩列相關。因此,如果您使用post_date作爲索引中的第三列,那麼優化器知道它可以按索引中存儲的順序獲取行,並且可以跳過爲ORDER BY執行任何其他工作。如果「使用filesort」從EXPLAIN輸出中消失,你可以看到這個工作正常。

所以有可能你的指標應該是:

ALTER TABLE wp_posts ADD INDEX (post_status, post_type, post_date); 

您還可以享受我的介紹How to Design Indexes, Really

在這種情況下,您不需要將ID添加到索引,因爲InnoDB索引會自動包含主鍵列。

LIMIT 18310, 5一定是昂貴的。 MySQL必須在服務器端生成整個結果集,最多18315行,僅丟棄大部分結果集。誰在世界上需要跳到3662 頁面,無論如何?!

SQL_CALC_FOUND_ROWS主要性能殺手,當你有,你通過分頁大的結果集,因爲MySQL會產生整個結果集,之前和您請求的頁面之後。除非你確實需要FOUND_ROWS(),並且即使你確實需要行數,它也可以更快地運行兩個查詢,其中一個用SELECT COUNT(*)
(*測試兩種方式,以確保。)

下面是優化LIMIT一些提示:

+1

我認爲WordPress的(舊?)安裝有MyISAM作爲默認引擎。 –

0

只是爲了讓你知道我在不同的個人電腦上,所以我的用戶名已經改變,但我確實寫了原始問題。

我認爲會很有幫助的是一個轉換指南,以幫助MS SQL背景的人轉換爲MySQL,因爲它似乎有一些索引調整的差異我沒有意識到,特別是不同的存儲引擎自動添加主鍵以及如何處理缺乏幫助性能調整的工具。

我用來創建我的主要聚集索引,主鍵等獨特的約束和索引,然後用鑰匙包括非聚集索引,一些覆蓋索引等

然後我將運行定時作業登錄缺失的索引DMV會向表中報告,以防止數據在任何重新啓動期間丟失。然後,我可以運行報告來檢查SQL優化器認爲「應該」使用的索引或那些「不」使用的索引。然後,我可以使用這些信息,如果使用了缺失索引,則可以使用錯誤匹配和潛在效率百分比的計數器,作爲幫助對索引進行性能優化的指導。

據我可以告訴MySQL沒有類似於DMV的MsSQL有什麼?

很好的圖形執行計劃內置於MS SQL Studio從以前的幫助調整了很多,沼澤標準的MySQL解釋比較差。我會研究你提到的那個工具,雖然運行一個select @@ version會返回5.0.51a-24 + lenny5-log,所以我懷疑它會幫助我。

幾件事情雖然有關帖子:

  1. 的目的是爲了有一個覆蓋索引所以沒有書籤查找(如果你在MySQL這樣稱呼)的要求,而且數據是從哪裏來的直該指數。由於幾乎所有我的帖子都是「發佈」(99.99%),而post_type幾乎都是「帖子」(99.99%),只有很少的「頁面」比例。這兩列沒有選擇性,它們在封面的索引中。我已經關閉了自動草稿以防止修改等,並且草稿的數量非常小。

  2. 因此,我會認爲有post_date作爲索引中的第一個鍵會有更多的幫助,因爲LIMIT(因爲你說是昂貴的,我無法控制Wordpress的代碼),所以肯定是ORDER BY和LIMIT(這基本上是一個TOP)將是查詢中最昂貴和選擇性最高的部分,並且與其他鍵(它們根本不具有選擇性)相比,索引有更多的用途。這就是爲什麼我先說。

  3. 我使用的是Wordpress,表格是wp_posts,它的存儲引擎是MyISAM,我相信由於要求它具有全文搜索功能,所以我不能更改它。

  4. 至於我對別人說我已經有順序post_type,post_status和POST_DATE的索引,但只能解釋它顯示在可能的密鑰,然後忽略它周圍使用這些列基於指數:post_status ,密碼和編號

  5. 由於密碼沒有在查詢中使用和post_status完全是無選擇性的(因爲我所有的post_types是「後」),我爲什麼MySQL的「聰明」的優化器認爲該指數應高於選擇虧損提供的還是我自己的?

所以我仍然堅持,因爲沒有任何建議似乎工作。

我試過多次改變順序,即使我只有20k行,每次需要半個小時或更多!我不知道在MySQL中這是否正常,但在MSSQL中,只需幾分鐘就可以在具有數百萬行的表上添加/刪除索引。

因此,迄今爲止沒有任何工作,我想知道(爲什麼?),顯然有關查詢提示,看看它是否有任何好處。

重新編制索引(甚至重新啓動網絡服務器)後,我重新啓動了數據庫。

感謝您的幫助。

+0

對不起,但我不會說這個問題已經回答了。所以我不知道爲什麼它被標記爲回答。作爲解決方案提供的索引沒有被使用。答案中唯一有用的部分是如何添加查詢提示。沒有解釋爲什麼2個非選擇鍵應當在LIMIT語句的最重要鍵(即post_date)的前面,或者爲什麼使用帶有密碼&id和非選擇性post_status的索引而不是任何其他選項提供。 – user2334626

+0

有沒有人有關於爲什麼使用非選擇性索引的答案呢? –