時(shí)間:2015-06-28 00:00:00 來(lái)源:IT貓撲網(wǎng) 作者:網(wǎng)管聯(lián)盟 我要評(píng)論(3)
本文介紹了數(shù)據(jù)庫(kù)索引,及其優(yōu)、缺點(diǎn)。針對(duì)MySQL索引的特點(diǎn)、應(yīng)用進(jìn)行了詳細(xì)的描述。分析了如何避免MySQL無(wú)法使用,如何使用EXPLAIN分析查詢語(yǔ)句,如何優(yōu)化MySQL索引的應(yīng)用。
索引是一種特殊的文件(InnoDB數(shù)據(jù)表上的索引是表空間的一個(gè)組成部分),它們包含著對(duì)數(shù)據(jù)表里所有記錄的引用指針。
注:
[1]索引不是萬(wàn)能的!
索引可以加快數(shù)據(jù)檢索操作,但會(huì)使數(shù)據(jù)修改操作變慢。每修改數(shù)據(jù)記錄,索引就必須刷新一次。為了在某種程序上彌補(bǔ)這一缺陷,許多SQL命令都有一個(gè)DELAY_KEY_WRITE項(xiàng)。這個(gè)選項(xiàng)的作用是暫時(shí)制止MySQL在該命令每插入一條新記錄和每修改一條現(xiàn)有之后立刻對(duì)索引進(jìn)行刷新,對(duì)索引的刷新將等到全部記錄插入/修改完畢之后再進(jìn)行。在需要把許多新記錄插入某個(gè)數(shù)據(jù)表的場(chǎng)合,DELAY_KEY_WRITE選項(xiàng)的作用將非常明顯。
[2]另外,索引還會(huì)在硬盤上占用相當(dāng)大的空間。
因此應(yīng)該只為最經(jīng)常查詢和最經(jīng)常排序的數(shù)據(jù)列建立索引。注意,如果某個(gè)數(shù)據(jù)列包含許多重復(fù)的內(nèi)容,為它建立索引就沒(méi)有太大的實(shí)際效果。
從理論上講,完全可以為數(shù)據(jù)表里的每個(gè)字段分別建一個(gè)索引,但MySQL把同一個(gè)數(shù)據(jù)表里的索引總數(shù)限制為16個(gè)。
1. InnoDB數(shù)據(jù)表的索引
與MyISAM數(shù)據(jù)表相比,索引對(duì)InnoDB數(shù)據(jù)的重要性要大得多。在InnoDB數(shù)據(jù)表上,索引對(duì)InnoDB數(shù)據(jù)表的重要性要在得多。在 InnoDB數(shù)據(jù)表上,索引不僅會(huì)在搜索數(shù)據(jù)記錄時(shí)發(fā)揮作用,還是數(shù)據(jù)行級(jí)鎖定機(jī)制的苊、基礎(chǔ)。"數(shù)據(jù)行級(jí)鎖定"的意思是指在事務(wù)操作的執(zhí)行過(guò)程中鎖定正在被處理的個(gè)別記錄,不讓其他用戶進(jìn)行訪問(wèn)。這種鎖定將影響到(但不限于)SELECT…LOCK IN SHARE MODE、SELECT…FOR UPDATE命令以及INSERT、UPDATE和DELETE命令。
出于效率方面的考慮,InnoDB數(shù)據(jù)表的數(shù)據(jù)行級(jí)鎖定實(shí)際發(fā)生在它們的索引上,而不是數(shù)據(jù)表自身上。顯然,數(shù)據(jù)行級(jí)鎖定機(jī)制只有在有關(guān)的數(shù)據(jù)表有一個(gè)合適的索引可供鎖定的時(shí)候才能發(fā)揮效力。
2. 限制
如果WEHERE子句的查詢條件里有不等號(hào)(WHERE coloum != …),MySQL將無(wú)法使用索引。
類似地,如果WHERE子句的查詢條件里使用了函數(shù)(WHERE DAY(column) = …),MySQL也將無(wú)法使用索引。
在JOIN操作中(需要從多個(gè)數(shù)據(jù)表提取數(shù)據(jù)時(shí)),MySQL只有在主鍵和外鍵的數(shù)據(jù)類型相同時(shí)才能使用索引。
如果WHERE子句的查詢條件里使用比較操作符LIKE和REGEXP,MySQL只有在搜索模板的第一個(gè)字符不是通配符的情況下才能使用索引。比如說(shuō),如果查詢條件是LIKE ‘a(chǎn)bc%’,MySQL將使用索引;如果查詢條件是LIKE ‘%abc’,MySQL將不使用索引。
在ORDER BY操作中,MySQL只有在排序條件不是一個(gè)查詢條件表達(dá)式的情況下才使用索引。(雖然如此,在涉及多個(gè)數(shù)據(jù)表查詢里,即使有索引可用,那些索引在加快ORDER BY方面也沒(méi)什么作用)
如果某個(gè)數(shù)據(jù)列里包含許多重復(fù)的值,就算為它建立了索引也不會(huì)有很好的效果。比如說(shuō),如果某個(gè)數(shù)據(jù)列里包含的凈是些諸如"0/1″或"Y/N"等值,就沒(méi)有必要為它創(chuàng)建一個(gè)索引。
普通索引、唯一索引和主索引
1. 普通索引
普通索引(由關(guān)鍵字KEY或INDEX定義的索引)的唯一任務(wù)是加快對(duì)數(shù)據(jù)的訪問(wèn)速度。因此,應(yīng)該只為那些最經(jīng)常出現(xiàn)在查詢條件(WHERE column = …)或排序條件(ORDER BY column)中的數(shù)據(jù)列創(chuàng)建索引。只要有可能,就應(yīng)該選擇一個(gè)數(shù)據(jù)最整齊、最緊湊的數(shù)據(jù)列(如一個(gè)整數(shù)類型的數(shù)據(jù)列)來(lái)創(chuàng)建索引。
2. 唯一索引
普通索引允許被索引的數(shù)據(jù)列包含重復(fù)的值。比如說(shuō),因?yàn)槿擞锌赡芡?,所以同一個(gè)姓名在同一個(gè)"員工個(gè)人資料"數(shù)據(jù)表里可能出現(xiàn)兩次或更多次。
如果能確定某個(gè)數(shù)據(jù)列將只包含彼此各不相同的值,在為這個(gè)數(shù)據(jù)列創(chuàng)建索引的時(shí)候就應(yīng)該用關(guān)鍵字UNIQUE把它定義為一個(gè)唯一索引。這么做的好處:一是簡(jiǎn)化了MySQL對(duì)這個(gè)索引的管理工作,這個(gè)索引也因此而變得更有效率;二是MySQL會(huì)在有新記錄插入數(shù)據(jù)表時(shí),自動(dòng)檢查新記錄的這個(gè)字段的值是否已經(jīng)在某個(gè)記錄的這個(gè)字段里出現(xiàn)過(guò)了;如果是,MySQL將拒絕插入那條新記錄。也就是說(shuō),唯一索引可以保證數(shù)據(jù)記錄的唯一性。事實(shí)上,在許多場(chǎng)合,人們創(chuàng)建唯一索引的目的往往不是為了提高訪問(wèn)速度,而只是為了避免數(shù)據(jù)出現(xiàn)重復(fù)。
3. 主索引
在前面已經(jīng)反復(fù)多次強(qiáng)調(diào)過(guò):必須為主鍵字段創(chuàng)建一個(gè)索引,這個(gè)索引就是所謂的"主索引"。主索引與唯一索引的唯一區(qū)別是:前者在定義時(shí)使用的關(guān)鍵字是PRIMARY而不是UNIQUE。
4. 外鍵索引
如果為某個(gè)外鍵字段定義了一個(gè)外鍵約束條件,MySQL就會(huì)定義一個(gè)內(nèi)部索引來(lái)幫助自己以最有效率的方式去管理和使用外鍵約束條件。
5. 復(fù)合索引
索引可以覆蓋多個(gè)數(shù)據(jù)列,如像INDEX(columnA, columnB)索引。這種索引的特點(diǎn)是MySQL可以有選擇地使用一個(gè)這樣的索引。如果查詢操作只需要用到columnA數(shù)據(jù)列上的一個(gè)索引,就可以使用復(fù)合索引INDEX(columnA, columnB)。不過(guò),這種用法僅適用于在復(fù)合索引中排列在前的數(shù)據(jù)列組合。比如說(shuō),INDEX(A, B, C)可以當(dāng)做A或(A, B)的索引來(lái)使用,但不能當(dāng)做B、C或(B, C)的索引來(lái)使用。
#p#副標(biāo)題#e#
6. 索引的長(zhǎng)度
在為CHAR和VARCHAR類型的數(shù)據(jù)列定義索引時(shí),可以把索引的長(zhǎng)度限制為一個(gè)給定的字符個(gè)數(shù)(這個(gè)數(shù)字必須小于這個(gè)字段所允許的最大字符個(gè)數(shù))。這么做的好處是可以生成一個(gè)尺寸比較小、檢索速度卻比較快的索引文件。在絕大多數(shù)應(yīng)用里,數(shù)據(jù)庫(kù)中的字符串?dāng)?shù)據(jù)大都以各種各樣的名字為主,把索引的長(zhǎng)度設(shè)置為10~15個(gè)字符已經(jīng)足以把搜索范圍縮小到很少的幾條數(shù)據(jù)記錄了。
在為BLOB和TEXT類型的數(shù)據(jù)列創(chuàng)建索引時(shí),必須對(duì)索引的長(zhǎng)度做出限制;MySQL所允許的最大索引長(zhǎng)度是255個(gè)字符。
全文索引
文本字段上的普通索引只能加快對(duì)出現(xiàn)在字段內(nèi)容最前面的字符串(也就是字段內(nèi)容開頭的字符)進(jìn)行檢索操作。如果字段里存放的是由幾個(gè)、甚至是多個(gè)單詞構(gòu)成的較大段文字,普通索引就沒(méi)什么作用了。這種檢索往往以LIKE %word%的形式出現(xiàn),這對(duì)MySQL來(lái)說(shuō)很復(fù)雜,如果需要處理的數(shù)據(jù)量很大,響應(yīng)時(shí)間就會(huì)很長(zhǎng)。
這類場(chǎng)合正是全文索引(full-text index)可以大顯身手的地方。在生成這種類型的索引時(shí),MySQL將把在文本中出現(xiàn)的所有單詞創(chuàng)建為一份清單,查詢操作將根據(jù)這份清單去檢索有關(guān)的數(shù)據(jù)記錄。全文索引即可以隨數(shù)據(jù)表一同創(chuàng)建,也可以等日后有必要時(shí)再使用下面這條命令添加:ALTER TABLE tablename ADD FULLTEXT(column1, column2) 有了全文索引,就可以用SELECT查詢命令去檢索那些包含著一個(gè)或多個(gè)給定單詞的數(shù)據(jù)記錄了。
下面是這類查詢命令的基本語(yǔ)法:
SELECT * FROM tablename WHERE MATCH(column1, column2) AGAINST(’word1′, ‘word2′, ‘word3′) |
上面這條命令將把column1和column2字段里有word1、word2和word3的數(shù)據(jù)記錄全部查詢出來(lái)。
注解:InnoDB數(shù)據(jù)表不支持全文索引。
查詢和索引的優(yōu)化
只有當(dāng)數(shù)據(jù)庫(kù)里已經(jīng)有了足夠多的測(cè)試數(shù)據(jù)時(shí),它的性能測(cè)試結(jié)果才有實(shí)際參考價(jià)值。如果在測(cè)試數(shù)據(jù)庫(kù)里只有幾百條數(shù)據(jù)記錄,它們往往在執(zhí)行完第一條查詢命令之后就被全部加載到內(nèi)存里,這將使后續(xù)的查詢命令都執(zhí)行得非??歙C不管有沒(méi)有使用索引。只有當(dāng)數(shù)據(jù)庫(kù)里的記錄超過(guò)了1000條、數(shù)據(jù)總量也超過(guò)了 MySQL服務(wù)器上的內(nèi)存總量時(shí),數(shù)據(jù)庫(kù)的性能測(cè)試結(jié)果才有意義。
在不確定應(yīng)該在哪些數(shù)據(jù)列上創(chuàng)建索引的時(shí)候,人們從EXPLAIN SELECT命令那里往往可以獲得一些幫助。這其實(shí)只是簡(jiǎn)單地給一條普通的SELECT命令加一個(gè)EXPLAIN關(guān)鍵字作為前綴而已。有了這個(gè)關(guān)鍵字,MySQL將不是去執(zhí)行那條SELECT命令,而是去對(duì)它進(jìn)行分析。MySQL將以表格的形式把查詢的執(zhí)行過(guò)程和用到的索引(如果有的話)等信息列出來(lái)。
在EXPLAIN命令的輸出結(jié)果里,第1列是從數(shù)據(jù)庫(kù)讀取的數(shù)據(jù)表的名字,它們按被讀取的先后順序排列。type列指定了本數(shù)據(jù)表與其它數(shù)據(jù)表之間的關(guān)聯(lián)關(guān)系(JOIN)。在各種類型的關(guān)聯(lián)關(guān)系當(dāng)中,效率最高的是system,然后依次是const、eq_ref、ref、range、index和 All(All的意思是:對(duì)應(yīng)于上一級(jí)數(shù)據(jù)表里的每一條記錄,這個(gè)數(shù)據(jù)表里的所有記錄都必須被讀取一遍–這種情況往往可以用一索引來(lái)避免)。
possible_keys數(shù)據(jù)列給出了MySQL在搜索數(shù)據(jù)記錄時(shí)可選用的各個(gè)索引。key數(shù)據(jù)列是MySQL實(shí)際選用的索引,這個(gè)索引按字節(jié)計(jì)算的長(zhǎng)度在key_len數(shù)據(jù)列里給出。比如說(shuō),對(duì)于一個(gè)INTEGER數(shù)據(jù)列的索引,這個(gè)字節(jié)長(zhǎng)度將是4。如果用到了復(fù)合索引,在key_len數(shù)據(jù)列里還可以看到MySQL具體使用了它的哪些部分。作為一般規(guī)律,key_len數(shù)據(jù)列里的值越小越好(意思是更快)。
ref數(shù)據(jù)列給出了關(guān)聯(lián)關(guān)系中另一個(gè)數(shù)據(jù)表里的數(shù)據(jù)列的名字。row數(shù)據(jù)列是MySQL在執(zhí)行這個(gè)查詢時(shí)預(yù)計(jì)會(huì)從這個(gè)數(shù)據(jù)表里讀出的數(shù)據(jù)行的個(gè)數(shù)。row數(shù)據(jù)列里的所有數(shù)字的乘
關(guān)鍵詞標(biāo)簽:MySQL 索引
相關(guān)閱讀
熱門文章 Xbox Game Pass 10款MySQL數(shù)據(jù)庫(kù)客戶端圖形界面管理工具推薦 MySQL常用維護(hù)管理工具 MySQL數(shù)據(jù)庫(kù)啟動(dòng)失敗1067進(jìn)程意外終止的解決辦法總結(jié)
人氣排行 10款MySQL數(shù)據(jù)庫(kù)客戶端圖形界面管理工具推薦 MySQL數(shù)據(jù)庫(kù)啟動(dòng)失敗1067進(jìn)程意外終止的解決辦法總結(jié) Mysql 1045錯(cuò)誤解決辦法 MySQL服務(wù)器進(jìn)程CPU占用100%解決辦法 MySQL導(dǎo)出導(dǎo)入命令的用例 MySQL連接字符串的實(shí)際操作步驟匯總 MySQL無(wú)法啟動(dòng)、無(wú)法停止各種解決方法總結(jié) 三種常用的MySQL建表語(yǔ)句