分(fēn)享到:

mysql索引的類型和優缺點

日(rì)期:2017-01-06 14:52:00     閱讀(dú):506     文章(zhāng)來(lái)源:源美網絡     标簽:深圳網站(zhàn)建設,深圳網站(zhàn)制作(zuò),mysql

現在來(lái)介紹了數據庫索引,及其優、缺點。針對MySQL索引的特點、應用進行了詳細的描 述。分(fēn)析了如(rú)何避免MySQL無法使用,如(rú)何使用EXPLAIN分(fēn)析查詢語句,如(rú)何優化MySQL索引的應用。本文摘自(zì)《MySQL 5權威指南(nán)》(3rd)的8.9節。


索引是一種特殊的文件(jiàn)(InnoDB數據表上的索引是表空間的一個組成部分(fēn)),它們包含着對數據表裡(lǐ)所有記錄的引用指針。

注:[1]索引不是萬能的!索引可(kě)以加快(kuài)數據檢索操作(zuò),但(dàn)會使數據修改操作(zuò)變慢(màn)。每修改數據記錄,索引就(jiù)必須刷新一次。爲了在某種程序上彌補這一缺陷,許 多SQL命令都(dōu)有一個DELAY_KEY_WRITE項。這個選項的作(zuò)用是暫時制止MySQL在該命令每插入一條新記錄和每修改一條現有之後立刻對索引進 行刷新,對索引的刷新将等到全部記錄插入/修改完畢之後再進行。在需要把許多新記錄插入某個數據表的場合,DELAY_KEY_WRITE選項的作(zuò)用将非 常明顯。[2]另外,索引還(hái)會在硬盤上占用相(xiàng)當大(dà)的空間。因此應該隻爲最經常查詢和最經常排序的數據列建立索引。注意,如(rú)果某個數據列包含許多重複的内 容,爲它建立索引就(jiù)沒有太大(dà)的實際效果。

從(cóng)理(lǐ)論上講,完全可(kě)以爲數據表裡(lǐ)的每個字段分(fēn)别建一個索引,但(dàn)MySQL把同一個數據表裡(lǐ)的索引總數限制爲16個。


1. InnoDB數據表的索引

與MyISAM數據表相(xiàng)比,索引對InnoDB數據的重要性要大(dà)得(de)多。在InnoDB數據表上,索引對InnoDB數據表的重要性要在得(de)多。在 InnoDB數據表上,索引不僅會在搜索數據記錄時發揮作(zuò)用,還(hái)是數據行級鎖定機(jī)制的苊、基礎。”數據行級鎖定”的意思是指在事(shì)務操作(zuò)的執行過程中鎖定正 在被處理(lǐ)的個别記錄,不讓其他(tā)用戶進行訪問(wèn)。這種鎖定将影(yǐng)響到(但(dàn)不限于)SELECT…LOCK IN SHARE MODE、SELECT…FOR UPDATE命令以及INSERT、UPDATE和DELETE命令。

出于效率方面的考慮,InnoDB數據表的數據行級鎖定實際發生(shēng)在它們的索引上,而不是數據表自(zì)身(shēn)上。顯然,數據行級鎖定機(jī)制隻有在有關的數據表有一個合 适的索引可(kě)供鎖定的時候才能發揮效力。


2. 限制

如(rú)果WEHERE子句的查詢條件(jiàn)裡(lǐ)有不等号(WHERE coloum != …),MySQL将無法使用索引。

類似地,如(rú)果WHERE子句的查詢條件(jiàn)裡(lǐ)使用了函數(WHERE DAY(column) = …),MySQL也将無法使用索引。

在JOIN操作(zuò)中(需要從(cóng)多個數據表提取數據時),MySQL隻有在主鍵和外鍵的數據類型相(xiàng)同時才能使用索引。

如(rú)果WHERE子句的查詢條件(jiàn)裡(lǐ)使用比較操作(zuò)符LIKE和REGEXP,MySQL隻有在搜索模闆的第一個字符不是通配符的情況下才能使用索引。比如(rú)說(shuō), 如(rú)果查詢條件(jiàn)是LIKE ‘abc%’,MySQL将使用索引;如(rú)果查詢條件(jiàn)是LIKE ‘%abc’,MySQL将不使用索引。

在ORDER BY操作(zuò)中,MySQL隻有在排序條件(jiàn)不是一個查詢條件(jiàn)表達式的情況下才使用索引。(雖然如(rú)此,在涉及多個數據表查詢裡(lǐ),即使有索引可(kě)用,那些索引在加快(kuài) ORDER BY方面也沒什麽作(zuò)用)

如(rú)果某個數據列裡(lǐ)包含許多重複的值,就(jiù)算爲它建立了索引也不會有很好的效果。比如(rú)說(shuō),如(rú)果某個數據列裡(lǐ)包含的淨是些諸如(rú)”0/1″或”Y/N”等值,就(jiù)沒 有必要爲它創建一個索引。


普通索引、唯一索引和主索引

1. 普通索引

普通索引(由關鍵字KEY或INDEX定義的索引)的唯一任務是加快(kuài)對數據的訪問(wèn)速度。因此,應該隻爲那些最經常出現在查詢條件(jiàn)(WHERE column = …)或排序條件(jiàn)(ORDER BY column)中的數據列創建索引。隻要有可(kě)能,就(jiù)應該選擇一個數據最整齊、最緊湊的數據列(如(rú)一個整數類型的數據列)來(lái)創建索引。

2. 唯一索引

普通索引允許被索引的數據列包含重複的值。比如(rú)說(shuō),因爲人(rén)有可(kě)能同名,所以同一個姓名在同一個”員(yuán)工(gōng)個人(rén)資料”數據表裡(lǐ)可(kě)能出現兩次或更多次。

如(rú)果能确定某個數據列将隻包含彼此各不相(xiàng)同的值,在爲這個數據列創建索引的時候就(jiù)應該用關鍵字UNIQUE把它定義爲一個唯一索引。這麽做的好處:一是簡 化了MySQL對這個索引的管理(lǐ)工(gōng)作(zuò),這個索引也因此而變得(de)更有效率;二是MySQL會在有新記錄插入數據表時,自(zì)動檢查新記錄的這個字段的值是否已經在 某個記錄的這個字段裡(lǐ)出現過了;如(rú)果是,MySQL将拒絕插入那條新記錄。也就(jiù)是說(shuō),唯一索引可(kě)以保證數據記錄的唯一性。事(shì)實上,在許多場合,人(rén)們創建唯 一索引的目的往往不是爲了提高訪問(wèn)速度,而隻是爲了避免數據出現重複。

3. 主索引

在前面已經反複多次強調過:必須爲主鍵字段創建一個索引,這個索引就(jiù)是所謂的”主索引”。主索引與唯一索引的唯一區别是:前者在定義時使用的關鍵字是 PRIMARY而不是UNIQUE。

4. 外鍵索引

如(rú)果爲某個外鍵字段定義了一個外鍵約束條件(jiàn),MySQL就(jiù)會定義一個内部索引來(lái)幫助自(zì)己以最有效率的方式去(qù)管理(lǐ)和使用外鍵約束條件(jiàn)。

5. 複合索引

索引可(kě)以覆蓋多個數據列,如(rú)像INDEX(columnA, columnB)索引。這種索引的特點是MySQL可(kě)以有選擇地使用一個這樣的索引。如(rú)果查詢操作(zuò)隻需要用到columnA數據列上的一個索引,就(jiù)可(kě)以使 用複合索引INDEX(columnA, columnB)。不過,這種用法僅适用于在複合索引中排列在前的數據列組合。比如(rú)說(shuō),INDEX(A, B, C)可(kě)以當做A或(A, B)的索引來(lái)使用,但(dàn)不能當做B、C或(B, C)的索引來(lái)使用。

6. 索引的長度

在爲CHAR和VARCHAR類型的數據列定義索引時,可(kě)以把索引的長度限制爲一個給定的字符個數(這個數字必須小于這個字段所允許的最大(dà)字符個數)。這 麽做的好處是可(kě)以生(shēng)成一個尺寸比較小、檢索速度卻比較快(kuài)的索引文件(jiàn)。在絕大(dà)多數應用裡(lǐ),數據庫中的字符串數據大(dà)都(dōu)以各種各樣的名字爲主,把索引的長度設置 爲10~15個字符已經足以把搜索範圍縮小到很少的幾條數據記錄了。

在爲BLOB和TEXT類型的數據列創建索引時,必須對索引的長度做出限制;MySQL所允許的最大(dà)索引長度是255個字符。


全文索引

文本字段上的普通索引隻能加快(kuài)對出現在字段内容最前面的字符串(也就(jiù)是字段内容開頭的字符)進行檢索操作(zuò)。如(rú)果字段裡(lǐ)存放(fàng)的是由幾個、甚至是多個單詞構成 的較大(dà)段文字,普通索引就(jiù)沒什麽作(zuò)用了。這種檢索往往以LIKE %word%的形式出現,這對MySQL來(lái)說(shuō)很複雜,如(rú)果需要處理(lǐ)的數據量很大(dà),響應時間就(jiù)會很長。

這類場合正是全文索引(full-text index)可(kě)以大(dà)顯身(shēn)手的地方。在生(shēng)成這種類型的索引時,MySQL将把在文本中出現的所有單詞創建爲一份清單,查詢操作(zuò)将根據這份清單去(qù)檢索有關的數 據記錄。全文索引即可(kě)以随數據表一同創建,也可(kě)以等日(rì)後有必要時再使用下面這條命令添加:

ALTER TABLE tablename ADD FULLTEXT(column1, column2)

有了全文索引,就(jiù)可(kě)以用SELECT查詢命令去(qù)檢索那些包含着一個或多個給定單詞的數據記錄了。下面是這類查詢命令的基本語法:

SELECT * FROM tablename

WHERE MATCH(column1, column2) AGAINST(‘word1′, ‘word2′, ‘word3′)

上面這條命令将把column1和column2字段裡(lǐ)有word1、word2和word3的數據記錄全部查詢出來(lái)。

注解:InnoDB數據表不支持全文索引。


查詢和索引的優化

隻有當數據庫裡(lǐ)已經有了足夠多的測試數據時,它的性能測試結果才有實際參考價值。如(rú)果在測試數據庫裡(lǐ)隻有幾百條數據記錄,它們往往在執行完第一條查詢命令 之後就(jiù)被全部加載到内存裡(lǐ),這将使後續的查詢命令都(dōu)執行得(de)非常快(kuài)–不管有沒有使用索引。隻有當數據庫裡(lǐ)的記錄超過了1000條、數據總量也超過了 MySQL服務器上的内存總量時,數據庫的性能測試結果才有意義。

在不确定應該在哪些數據列上創建索引的時候,人(rén)們從(cóng)EXPLAIN SELECT命令那裡(lǐ)往往可(kě)以獲得(de)一些幫助。這其實隻是簡單地給一條普通的SELECT命令加一個EXPLAIN關鍵字作(zuò)爲前綴而已。有了這個關鍵 字,MySQL将不是去(qù)執行那條SELECT命令,而是去(qù)對它進行分(fēn)析。MySQL将以表格的形式把查詢的執行過程和用到的索引(如(rú)果有的話(huà))等信息列出 來(lái)。

在EXPLAIN命令的輸出結果裡(lǐ),第1列是從(cóng)數據庫讀(dú)取的數據表的名字,它們按被讀(dú)取的先後順序排列。type列指定了本數據表與其它數據表之間的關聯 關系(JOIN)。在各種類型的關聯關系當中,效率最高的是system,然後依次是const、eq_ref、ref、range、index和 All(All的意思是:對應于上一級數據表裡(lǐ)的每一條記錄,這個數據表裡(lǐ)的所有記錄都(dōu)必須被讀(dú)取一遍–這種情況往往可(kě)以用一索引來(lái)避免)。

possible_keys數據列給出了MySQL在搜索數據記錄時可(kě)選用的各個索引。key數據列是MySQL實際選用的索引,這個索引按字節計(jì)算的長 度在key_len數據列裡(lǐ)給出。比如(rú)說(shuō),對于一個INTEGER數據列的索引,這個字節長度将是4。如(rú)果用到了複合索引,在key_len數據列裡(lǐ)還(hái)可(kě) 以看(kàn)到MySQL具體(tǐ)使用了它的哪些部分(fēn)。作(zuò)爲一般規律,key_len數據列裡(lǐ)的值越小越好(意思是更快(kuài))。

ref數據列給出了關聯關系中另一個數據表裡(lǐ)的數據列的名字。row數據列是MySQL在執行這個查詢時預計(jì)會從(cóng)這個數據表裡(lǐ)讀(dú)出的數據行的個數。row 數據列裡(lǐ)的所有數字的乘積可(kě)以讓我們大(dà)緻了解這個查詢需要處理(lǐ)多少組合。

最後,extra數據列提供了與JOIN操作(zuò)有關的更多信息,比如(rú)說(shuō),如(rú)果MySQL在執行這個查詢時必須創建一個臨時數據表,就(jiù)會在extra列看(kàn)到 using temporary字樣。



文章(zhāng)引用:

本站(zhàn)文章(zhāng)爲深圳網站(zhàn)建設·源美網絡原創策劃,如(rú)有版權糾紛或者違規問(wèn)題,請(qǐng)聯系我們删除,謝謝!

上一篇: 關于php識别二維碼

下一篇: 從(cóng)設計(jì)到創意,了解設計(jì)的提升關鍵點!

返回列表
最新案例
OUR ADVANTAGE WORKS

售後保障

承諾任何問(wèn)題1小時内解決

數據備份

更安全、更高效、更穩定

價格公道精準

項目經理(lǐ)精準報價不弄虛作(zuò)假

合作(zuò)無風(fēng)險

重合同講信譽,無效全額退款