2019/3/6 10:48:36
一、什(shén)麽是索引?
索引用(yòng)來快速地(dì)尋找那些具有(yǒu)特定值的(de)記錄,所有(yǒu)MySQL索引都(dōu)以B-樹的(de)形式保存。如(rú)果沒有(yǒu)索引,執行(xíng)查詢時MySQL必須從第一個(gè)記錄開(kāi)始掃描整個(gè)表的(de)所有(yǒu)記錄,直至找到(dào)符合要求的(de)記錄。表裏面的(de)記錄數量越多,這個(gè)操作的(de)代價就越高(gāo)。如(rú)果作爲搜索條件(jiàn)的(de)列上(shàng)已經創建了索引,MySQL無需掃描任何記錄即可(kě)迅速得到(dào)目标記錄所在的(de)位置。如(rú)果表有(yǒu)1000個(gè)記錄,通過索引查找記錄至少(shǎo)要比順序掃描記錄快100倍。
假設我們創建了一個(gè)名爲people的(de)表:
CREATE TABLE people ( peopleid SMALLINT NOT NULL, name CHAR(50) NOT NULL );
然後,我們完全随機把1000個(gè)不同name值插入到(dào)people表。下圖顯示了people表所在數據文(wén)件(jiàn)的(de)一小(xiǎo)部分(fēn):
可(kě)以看到(dào),在數據文(wén)件(jiàn)中name列沒有(yǒu)任何明(míng)确的(de)次序。如(rú)果我們創建了name列的(de)索引,MySQL将在索引中排序name列:
對于索引中的(de)每一項,MySQL在内部爲它保存一個(gè)數據文(wén)件(jiàn)中實際記錄所在位置的(de)“指針”。因此,如(rú)果我們要查找name等于“Mike”記錄的(de)peopleid(SQL命令爲“SELECT peopleid FROM people WHERE name=\'Mike\';”),MySQL能(néng)夠在name的(de)索引中查找“Mike”值,然後直接轉到(dào)數據文(wén)件(jiàn)中相(xiàng)應的(de)行(xíng),準确地(dì)返回該行(xíng)的(de)peopleid(999)。在這個(gè)過程中,MySQL隻需處理(lǐ)一個(gè)行(xíng)就可(kě)以返回結果。如(rú)果沒有(yǒu)“name”列的(de)索引,MySQL要掃描數據文(wén)件(jiàn)中的(de)所有(yǒu)記錄,即1000個(gè)記錄!顯然,需要MySQL處理(lǐ)的(de)記錄數量越少(shǎo),則它完成任務的(de)速度就越快。
二、索引的(de)類型
MySQL提供多種索引類型供選擇:
普通索引
這是最基本的(de)索引類型,而且它沒有(yǒu)唯一性之類的(de)限制(zhì)。普通索引可(kě)以通過以下幾種方式創建:
創建索引,例如(rú)CREATE INDEX <索引的(de)名字> ON tablename (列的(de)列表);
修改表,例如(rú)ALTER TABLE tablename ADD INDEX [索引的(de)名字] (列的(de)列表);
創建表的(de)時候指定索引,例如(rú)CREATE TABLE tablename ( [...], INDEX [索引的(de)名字] (列的(de)列表) );
唯一性索引
這種索引和(hé)前面的(de)“普通索引”基本相(xiàng)同,但(dàn)有(yǒu)一個(gè)區别:索引列的(de)所有(yǒu)值都(dōu)隻能(néng)出現一次,即必須唯一。唯一性索引可(kě)以用(yòng)以下幾種方式創建:
創建索引,例如(rú)CREATE UNIQUE INDEX <索引的(de)名字> ON tablename (列的(de)列表);
修改表,例如(rú)ALTER TABLE tablename ADD UNIQUE [索引的(de)名字] (列的(de)列表);
創建表的(de)時候指定索引,例如(rú)CREATE TABLE tablename ( [...], UNIQUE [索引的(de)名字] (列的(de)列表) );
主鍵
主鍵是一種唯一性索引,但(dàn)它必須指定爲“PRIMARY KEY”。如(rú)果你(nǐ)曾經用(yòng)過AUTO_INCREMENT類型的(de)列,你(nǐ)可(kě)能(néng)已經熟悉主鍵之類的(de)概念了。主鍵一般在創建表的(de)時候指定,例如(rú)“CREATE TABLE tablename ( [...], PRIMARY KEY (列的(de)列表) ); ”。但(dàn)是,我們也(yě)可(kě)以通過修改表的(de)方式加入主鍵,例如(rú)“ALTER TABLE tablename ADD PRIMARY KEY (列的(de)列表); ”。每個(gè)表隻能(néng)有(yǒu)一個(gè)主鍵。
全文(wén)索引
MySQL從3.23.23版開(kāi)始支持全文(wén)索引和(hé)全文(wén)檢索。在MySQL中,全文(wén)索引的(de)索引類型爲FULLTEXT。全文(wén)索引可(kě)以在VARCHAR或者TEXT類型的(de)列上(shàng)創建。它可(kě)以通過CREATE TABLE命令創建,也(yě)可(kě)以通過ALTER TABLE或CREATE INDEX命令創建。對于大(dà)規模的(de)數據集,通過ALTER TABLE(或者CREATE INDEX)命令創建全文(wén)索引要比把記錄插入帶有(yǒu)全文(wén)索引的(de)空表更快。本文(wén)下面的(de)討(tǎo)論不再涉及全文(wén)索引,要了解更多信息,請參見MySQL documentation。
三、單列索引與多列索引
索引可(kě)以是單列索引,也(yě)可(kě)以是多列索引。下面我們通過具體的(de)例子來說明(míng)這兩種索引的(de)區别。假設有(yǒu)這樣一個(gè)people表:
ALTER TABLE people ADD INDEX fname_lname_age (firstname,lastname,age);
由于索引文(wén)件(jiàn)以B-樹格式保存,MySQL能(néng)夠立即轉到(dào)合适的(de)firstname,然後再轉到(dào)合适的(de)lastname,最後轉到(dào)合适的(de)age。在沒有(yǒu)掃描數據文(wén)件(jiàn)任何一個(gè)記錄的(de)情況下,MySQL就正确地(dì)找出了搜索的(de)目标記錄!
那麽,如(rú)果在firstname、lastname、age這三個(gè)列上(shàng)分(fēn)别創建單列索引,效果是否和(hé)創建一個(gè)firstname、lastname、age的(de)多列索引一樣呢?答案是否定的(de),兩者完全不同。當我們執行(xíng)查詢的(de)時候,MySQL隻能(néng)使用(yòng)一個(gè)索引。如(rú)果你(nǐ)有(yǒu)三個(gè)單列的(de)索引,MySQL會(huì)試圖選擇一個(gè)限制(zhì)最嚴格的(de)索引。但(dàn)是,即使是限制(zhì)最嚴格的(de)單列索引,它的(de)限制(zhì)能(néng)力也(yě)肯定遠遠低于firstname、lastname、age這三個(gè)列上(shàng)的(de)多列索引。
四、最左前綴
多列索引還有(yǒu)另外一個(gè)優點,它通過稱爲最左前綴(Leftmost Prefixing)的(de)概念體現出來。繼續考慮前面的(de)例子,現在我們有(yǒu)一個(gè)firstname、lastname、age列上(shàng)的(de)多列索引,我們稱這個(gè)索引爲fname_lname_age。當搜索條件(jiàn)
深圳市南山區南山街(jiē)道南海(hǎi)大(dà)道西(xī)桂廟路(lù)北陽光(guāng)華藝大(dà)廈1棟4F、4G-04
咨詢電話(huà):136 8237 6272
大(dà)客戶咨詢:139 0290 5075
業(yè)務QQ:195006118
技術(shù)QQ:179981967