2010-06-15 136 views
162

我一直在我的MySQL數據庫中使用索引一段時間,但從來沒有正確瞭解關於他們。一般來說,我會在搜索或選擇使用WHERE條款的任何字段上放置索引,但有時它看起來不那麼黑白。MySQL索引 - 什麼是最佳實踐?

什麼是MySQL索引的最佳實踐?

例的情況下/困境:

如果一個表有六列,所有的 它們是可搜索的,我應該指數 所有這些人或沒有?

什麼是負面表現 索引的影響?

如果我有一個VARCHAR 2500柱,其 是從我的網站的部分搜索, 我應該索引呢?

+3

你應該重申這個問題。索引的選擇是優化任何數據庫模型的重要部分。和我的觀點無關的PHP。 – VGE 2010-12-31 14:18:41

回答

8

加載數據高效:指數加速檢索,但在索引列放慢值的插入和刪除,以及更新。也就是說,索引減緩了涉及編寫的大部分操作。發生這種情況是因爲寫入行需要寫入數據行,它也需要更改任何索引。表格具有的索引越多,需要進行的更改越多,並且平均性能下降越大。大多數表獲得很多讀取和很少寫入,但對於寫入比例很高的表,索引更新的成本可能很高。

避免索引:如果您不需要特定的索引來幫助查詢更好地執行,請不要創建它。

磁盤空間:索引佔用磁盤空間,多個索引佔用相應更多的空間。這可能會導致您比沒有索引時更快地達到表格大小限制。儘可能避免索引。

外賣:不要過度指數

3

1/2)指數加速某些選擇操作,但他們慢下來一樣插入,更新等操作,並刪除。它可以是一個很好的平衡。

3)使用全文索引,或者是獅身人面像

+0

爲了防止'減緩像插入,更新等操作,並deletes'可以使用 'START TRANSACTION;'' 您的代碼在這裏,'' COMMIT' 這可以幫助避免'放緩down'其他操作,如它只會檢查一次約束條件。 CAVEAT:如果使用REPLACE INTO和SQL_MODE STRICT_ALL_TABLES或TRADITIONAL'Bulk Load'將忽略替換和插入重複項。 – JayRizzo 2017-06-23 16:59:11

19

如果一個表有六列和所有的人都搜索,我應該指數所有這些人或無

是你是按字段搜索還是使用多個字段進行搜索? 哪個字段是最多正在搜索? 什麼是字段類型? (例如,索引在INT上比在VARCHAR上效果更好) 您是否嘗試在正在運行的查詢上使用EXPLAIN?

什麼是索引的negetive性能影響

更新和插入速度會變慢。還有額外的存儲空間需求,但這些通常不重要。

如果我有一個VARCHAR 2500柱,這是搜索的從我的網站的一部分,我應該索引呢

沒有,除非它獨特的(這意味着它已經索引),或者你只搜索確切的匹配該字段(不使用LIKE或mySQL的全文搜索)。

一般來說,我把一個指標上,我將在搜索或選擇任何字段使用WHERE子句

我通常索引是最查詢的字段,然後在INT /布爾/枚舉而不是那些是VARCHARS的字段。不要忘記,通常您需要在組合字段上創建索引,而不是單個字段上的索引。使用EXPLAIN,並檢查慢日誌。

42

查看演示文稿,如More Mastering the Art of Indexing

更新12/2012:我發佈了我的新演示文稿:How to Design Indexes, Really。我於2012年10月在聖克拉拉的ZendCon展會上以及2012年12月在Percona Live London上展示了這一點。

設計最佳索引是一個必須與您在應用中運行的查詢相匹配的過程。

很難推薦關於哪些列最適合索引,或者應該索引所有列,沒有列,哪些索引應該跨越多列等的通用規則。這取決於您需要運行的查詢。

是的,有一些開銷,所以你不應該不必要地創建索引。但是你應該應該創建索引,使您需要快速運行的查詢的好處。指數的開銷通常遠遠超過其收益。

對於列,它是VARCHAR(2500),你可能想使用FULLTEXT index或前綴索引:

CREATE INDEX i ON SomeTable(longVarchar(100)); 

需要注意的是傳統的指數不能幫助,如果您正在搜索詞可能在那個long varchar的中間。爲此,請使用全文索引。

+2

非常感謝。確實,這個網站確實非常有幫助。 – RY35 2015-10-29 09:31:59

37

我就不重複了一些在其他的答案了很好的建議,但會增加:

複合指數

您可以創建複合指數 - 包括多列的索引。 MySQL可以使用這些從左邊右邊。所以,如果您有:

Table A 
Id 
Name 
Category 
Age 
Description 

,如果你有一個包括按順序名稱/分類/年齡一個複合索引,這些WHERE子句將使用索引:

WHERE Name='Eric' and Category='A' 

WHERE Name='Eric' and Category='A' and Age > 18 

WHERE Category='A' and Age > 18 

不會使用該索引,因爲一切都必須從左到右使用。

解釋

使用EXPLAIN /解釋擴展明白了什麼指標可用於MySQL和哪一個真正選擇。 MySQL將只使用ONE密鑰每查詢

EXPLAIN EXTENDED SELECT * from Table WHERE Something='ABC' 

慢查詢日誌

接通slow query log,看看哪些查詢運行緩慢。

寬列

如果你有一個寬列,大部分的區別發生在第幾個字符,你可以在你的索引僅使用前N個字符。示例:我們將ReferenceNumber列定義爲varchar(255),但97%的情況下,參考編號爲10個字符或更少。我改變了索引,只查看前10個字符並改進了性能。

+0

我對最後一部分有疑問。我在某處讀到,如果您使用VARCHAR創建列,則應始終將其設置爲255.現在您說,設置爲此類列的索引可能僅限於查看前10個字符。你究竟如何做到這一點? – AlexioVay 2017-02-23 11:31:53

+0

'WHERE Name ='Eric'和Age> 18'會起作用嗎? – 2017-08-04 10:25:09

188

你應該花一些時間閱讀索引,寫了很多關於它的知識,瞭解發生了什麼很重要。

廣義上說,索引對錶格的行施加了排序。

爲了簡單起見,想象一下,表格只是一個很大的CSV文件。無論何時插入一行,它都會在的末尾插入。所以表格的「自然」順序就是插入行的順序。

想象一下,您已將該CSV文件加載到非常基本的電子表格應用程序中。所有這些電子表格都會顯示數據,並按順序對行進行編號。

現在設想您需要找到第三列中具有某個值「M」的所有行。鑑於你有什麼可用的,你只有一個選擇。您掃描表檢查每行的第三列的值。如果你有很多行,這種方法(「表掃描」)可能需要很長時間!

現在想象一下,除了這張表之外,你還有一個索引。這個特定的索引是第三列中的值的索引。該索引按照某種有意義的順序(例如,按字母順序)列出第三列中的所有值,併爲其中的每個值提供該值出現的行號列表。

現在你有一個很好的策略來找到第三列值爲「M」的所有行。例如,你可以執行一個binary search!鑑於表掃描要求您查看N行(其中N是行數),二進制搜索只需要查看log-n索引條目,最糟糕的情況是。哇,這當然容易多了!當然,如果你有這個索引,並且你正在向表中添加行(最後,因爲這就是我們的概念表的工作方式),你需要每次更新索引。所以,當你寫新的行時,你會做更多的工作,但是當你搜索某些東西的時候,你會節省大量的時間。

因此,一般來說,索引建立了讀取效率和寫入效率之間的折衷。沒有索引時,插入可以非常快 - 數據庫引擎只是在表中添加一行。在添加索引時,引擎必須在執行插入時更新每個索引。

另一方面,閱讀變得快得多。

希望涵蓋你的前兩個問題(正如其他人已經回答 - 你需要找到合適的平衡)。

你的第三種情況稍微複雜一點。如果您使用LIKE,索引引擎通常會幫助您將讀取速度提高到第一個「%」。換句話說,如果SELECTing WHERE列LIKE'foo%bar%',數據庫將使用索引查找列以「foo」開頭的所有行,然後需要掃描該中間行集以查找子集包含「欄」。 SELECT ... WHERE列LIKE'%bar%'不能使用索引。我希望你能明白爲什麼。

最後,您需要開始考慮多個列上的索引。這個概念是相同的,並且與LIKE的行爲類似 - essentialy,如果你有(a,b,c)上的索引,引擎將盡可能地從左到右繼續使用索引。因此,對列a的搜索可以使用(a,b,c)索引,就像(a,b)上的索引一樣。然而,如果你正在搜索WHERE b = 5 AND c = 1,那麼引擎需要做全表掃描。)

希望這有助於解決一些問題,但我必須重申,你最好花一些錢數小時挖掘好的文章,深入解釋這些事情。閱讀特定數據庫服務器的文檔也是一個好主意。查詢計劃人員實施和使用索引的方式差別很大。

+8

「FULLTEXT」索引怎麼樣?他們可以幫助像'LIKE'%bar%''這樣的條件嗎? – Septagram 2013-03-15 08:35:09

4

一般而言,索引有助於加速數據庫搜索,具有使用額外磁盤空間和減慢查詢速度的缺點。使用EXPLAIN並閱讀結果以瞭解MySQL何時使用您的索引。

如果一張表有六列,並且它們都是可搜索的,那麼我應該索引所有這些還是它們都沒有?

將所有六列索引並不總是最佳實踐。

(a)您在搜索特定信息時是否會使用這些列中的任何一列?

(b)這些列的選擇性是什麼(與表中記錄的總數相比,存儲了多少個不同的值)?

MySQL使用基於成本的優化器,它試圖在執行查詢時找到「最便宜」的路徑。選擇性低的領域不適合。

什麼是索引的性能影響?

已經回答:額外的磁盤空間,插入時更低的性能 - 更新 - 刪除。

如果我有一個VARCHAR 2500列可以從我的網站的部分搜索,我應該索引它?

嘗試FULLTEXT Index