MYSQL索引分析和優化設計方案

1、什麼是索引?數據庫


索引用來快速地尋找那些具備特定值的記錄,全部MySQL索引都以B-樹的形式保存。若是沒有索引,執行查詢時 MySQL必須從第一個記錄開始掃描整個表的全部記錄,直至找到符合要求的記錄。表裏面的記錄數量越多,這個操做的代價就越高。若是做爲搜索條件的列上已 經建立了索引,MySQL無需掃描任何記錄便可迅速獲得目標記錄所在的位置。若是表有1000個記錄,經過索引查找記錄至少要比順序掃描記錄快100倍。優化


假設咱們建立了一個名爲people的表:網站


CREATE TABLE people ( peopleid SMALLINT NOT NULL, name CHAR(50) NOT NULL );操作系統


而後,咱們徹底隨機把1000個不一樣name值插入到people表。下圖顯示了people表所在數據文件的一小部分:指針


能夠看到,在數據文件中name列沒有任何明確的次序。若是咱們建立了name列的索引,MySQL將在索引中排序name列:排序


對於索引中的每一項,MySQL在內部爲它保存一個數據文件中實際記錄所在位置的「指針」。所以,若是咱們要查找name等於「Mike」記錄的 peopleid(SQL命令爲「SELECT peopleid FROM people WHERE name=\’Mike\’;」),MySQL可以在name的索引中查找「Mike」值,而後直接轉到數據文件中相應的行,準確地返回該行的 peopleid(999)。在這個過程當中,MySQL只需處理一個行就能夠返回結果。若是沒有「name」列的索引,MySQL要掃描數據文件中的全部 記錄,即1000個記錄!顯然,須要MySQL處理的記錄數量越少,則它完成任務的速度就越快。索引


2、索引的類型文檔


MySQL提供多種索引類型供選擇:table


普通索引ast


這是最基本的索引類型,並且它沒有惟一性之類的限制。普通索引能夠經過如下幾種方式建立:


建立索引,例如CREATE INDEX <索引的名字> ON tablename (列的列表);修改表,例如ALTER TABLE tablename ADD INDEX [索引的名字] (列的列表);建立表的時候指定索引,例如CREATE TABLE tablename ( [...], INDEX [索引的名字] (列的列表) );惟一性索引


這種索引和前面的「普通索引」基本相同,但有一個區別:索引列的全部值都只能出現一次,即必須惟一。惟一性索引能夠用如下幾種方式建立:


建立索引,例如CREATE UNIQUE INDEX <索引的名字> ON tablename (列的列表);修改表,例如ALTER TABLE tablename ADD UNIQUE [索引的名字] (列的列表);建立表的時候指定索引,例如CREATE TABLE tablename ( [...], UNIQUE [索引的名字] (列的列表) );主鍵


主 鍵是一種惟一性索引,但它必須指定爲「PRIMARY KEY」。若是你曾經用過AUTO_INCREMENT類型的列,你可能已經熟悉主鍵之類的概念了。主鍵通常在建立表的時候指定,例如「CREATE TABLE tablename ( [...], PRIMARY KEY (列的列表) ); 」。可是,咱們也能夠經過修改表的方式加入主鍵,例如「ALTER TABLE tablename ADD PRIMARY KEY (列的列表); 」。每一個表只能有一個主鍵。


全文索引


MySQL從3.23.23版開始支持全文索引和全文檢索。 在MySQL中,全文索引的索引類型爲FULLTEXT。全文索引能夠在VARCHAR或者TEXT類型的列上建立。它能夠經過CREATE TABLE命令建立,也能夠經過ALTER TABLE或CREATE INDEX命令建立。對於大規模的數據集,經過ALTER TABLE(或者CREATE INDEX)命令建立全文索引要比把記錄插入帶有全文索引的空表更快。


3、單列索引與多列索引


索引能夠是單列索引,也能夠是多列索引。下面咱們經過具體的例子來講明這兩種索引的區別。假設有這樣一個people表:


ALTER TABLE people ADD INDEX fname_lname_age (firstname,lastname,age);


因爲索引文件以B-樹格式保存,MySQL可以當即轉到合適的firstname,而後再轉到合適的lastname,最後轉到合適的age。在沒 有掃描數據文件任何一個記錄的狀況下,MySQL就正確地找出了搜索的目標記錄!


那麼,若是在firstname、lastname、age這三個列上分別建立單列索引,效果是否和建立一個firstname、 lastname、 age的多列索引同樣呢?是否認的,二者徹底不一樣。當咱們執行查詢的時候,MySQL只能使用一個索引。若是你有三個單列的索引,MySQL會試圖選 擇一個限制最嚴格的索引。可是,即便是限制最嚴格的單列索引,它的限制能力也確定遠遠低於firstname、lastname、age這三個列上的多列 索引。


4、最左前綴


多列索引還有另一個優勢,它經過稱爲最左前綴 (Leftmost Prefixing)的概念體現出來。繼續前面的例子,如今咱們有一個firstname、lastname、age列上的多列索引,咱們稱這個索引 爲fname_lname_age。當搜索條件是如下各類列的組合時,MySQL將使用fname_lname_age索引:


firstname,lastname,agefirstname,lastnamefirstname


從另外一方面理解,它至關於咱們建立了(firstname,lastname,age)、(firstname,lastname)以及 (firstname)這些列組合上的索引。下面這些查詢都可以使用這個fname_lname_age索引:


table type possible_keys key key_len ref rows Extra


people ref fname_lname_age fname_lname_age 102 const,const,const 1 Where used


下面咱們就來看看這個EXPLAIN分析結果的含義。


table:這是表的名字。type:鏈接操做的類型。下面是MySQL文檔關於ref鏈接類型的說明:


「 對於每一種與另外一個表中記錄的組合,MySQL將從當前的表讀取全部帶有匹配索引值的記錄。若是鏈接操做只使用鍵的最左前綴,或者若是鍵不是UNIQUE 或PRIMARY KEY類型(換句話說,若是鏈接操做不能根據鍵值選擇出惟一行),則MySQL使用ref鏈接類型。若是鏈接操做所用的鍵只匹配少許的記錄,則ref是一 種好的鏈接類型。」


在本例中,因爲索引不是UNIQUE類型,ref是咱們可以獲得的最好鏈接類型。


若是EXPLAIN顯示鏈接類型是「ALL」,並且你並不想從表裏面選擇出大多數記錄,那麼MySQL的操做效率將很是低,由於它要掃描整個表。你 能夠加入更多的索引來解決這個問題。預知更多信息,請參見MySQL的手冊說明。


possible_keys:


可能能夠利用的索引的名字。這裏的索引名字是建立索引時指定的索引暱稱;若是索引沒有暱稱,則默認顯示的是索引中第一個列的名字(在本例中,它是 「firstname」)。默認索引名字的含義每每不是很明顯。


Key:


它顯示了MySQL實際使用的索引的名字。若是它爲空(或NULL),則MySQL不使用索引。


key_len:


索引中被使用部分的長度,以字節計。在本例中,key_len是102,其中firstname佔50字節,lastname佔50字節,age佔 2字節。若是MySQL只使用索引中的firstname部分,則key_len將是50。


ref:


它顯示的是列的名字(或單詞「const」),MySQL將根據這些列來選擇行。在本例中,MySQL根據三個常量選擇行。


rows:


MySQL所認爲的它在找到正確的結果以前必須掃描的記錄數。顯然,這裏最理想的數字就是1。


Extra:


這裏可能出現許多不一樣的選項,其中大多數將對查詢產生負面影響。在本例中,MySQL只是提醒咱們它將用WHERE子句限制搜索結果集。


7、索引的缺點


到目前爲止,咱們討論的都是索引的優勢。事實上,索引也是有缺點的。


首先,索引要佔用磁盤空間。一般狀況下,這個問題不是很突出。可是,若是你建立每一種可能列組合的索引,索引文件體積的增加速度將遠遠超過數據文 件。若是你有一個很大的表,索引文件的大小可能達到操做系統容許的最大文件限制。


第二,對於須要寫入數據的操做,好比DELETE、UPDATE以及INSERT操做,索引會下降它們的速度。這是由於MySQL不只要把改動數據 寫入數據文件,並且它還要把這些改動寫入索引文件。


【結束語】


在大型數據庫中,索引是提升速度的一個關鍵因素。無論表的結構是多麼簡單,一次500000行的表掃描操做不管如何不會快。若是你的網站上也有這種 大規 模的表,那麼你確實應該花些時間去分析能夠採用哪些索引,是否能夠改寫查詢以優化應用。另外注意,本文假定你所使用的MySQL是3.23版,部分 查詢不能在3.22版MySQL上執行。

相關文章
相關標籤/搜索