java mysql 全文索引_MySQL索引原理
什么是索引?
“索引”是為了能夠更快地查詢(xún)數(shù)據(jù)。比如一本書(shū)的目錄,就是這本書(shū)的內(nèi)容的索引,讀者可以通過(guò)在目錄中快速查找自己想要的內(nèi)容,然后根據(jù)頁(yè)碼去找到具體的章節(jié)。
數(shù)據(jù)庫(kù)也是一樣,如果查詢(xún)語(yǔ)句使用到了索引,會(huì)先去索引里面查詢(xún),取得數(shù)據(jù)所在行的物理地址,進(jìn)而訪問(wèn)數(shù)據(jù)。
索引的優(yōu)缺點(diǎn)
優(yōu)勢(shì):以快速檢索,減少I(mǎi)/O次數(shù),加快檢索速度;根據(jù)索引分組和排序,可以加快分組和排序;
劣勢(shì):索引本身也是表,因此會(huì)占用存儲(chǔ)空間。索引的維護(hù)和創(chuàng)建需要時(shí)間成本,這個(gè)成本隨著數(shù)據(jù)量增大而增大;構(gòu)建索引會(huì)降低數(shù)據(jù)表的修改操作(刪除,添加,修改)的效率,因?yàn)樵谛薷臄?shù)據(jù)表的同時(shí)還需要修改索引表。
索引的分類(lèi)
在MySQL中,常見(jiàn)的索引類(lèi)型有:主鍵索引、唯一索引、普通索引、全文索引、組合索引。創(chuàng)建語(yǔ)法分別為:
其中,組合索引又稱(chēng)為多列索引,上述代碼中最后一個(gè)例子就是建立了3列的索引。MySQL在根據(jù)索引查詢(xún)時(shí),會(huì)遵循“最左匹配”原則,即先根據(jù)col1的條件查,再根據(jù)col2的條件查,然后再根據(jù)col3的條件去查。
如果跳過(guò)了一個(gè)列直接查后面的列,比如下面的語(yǔ)句,就不能使用上面創(chuàng)建的索引了:
這里有一個(gè)小技巧,如果你前面的列是一個(gè)簡(jiǎn)單的枚舉類(lèi)型,比如性別等,可以用在where語(yǔ)句中加 col1 in(MALE, FEMALE) 來(lái)“跳過(guò)” col1 列,并使用上述索引。
對(duì)于某列如果是字符串且比較長(zhǎng)(比如UUID),推薦使用前綴索引,即匹配前n個(gè)字符。具體這個(gè)n取值多少是根據(jù)你的數(shù)據(jù)來(lái)的,《高性能MySQL》里提供了一個(gè)技巧:通過(guò)使用LEFT函數(shù)查詢(xún),從1開(kāi)始,不斷增加n的值,直到查詢(xún)結(jié)果的行數(shù)接近完整列的查詢(xún)結(jié)果的行數(shù),就是合適的n的值。
索引的實(shí)現(xiàn)原理
MySQL的索引是由存儲(chǔ)引擎來(lái)實(shí)現(xiàn)的。由于存儲(chǔ)引擎不同,所以具有不同的索引類(lèi)型,如BTree索引,B+Tree索引,哈希索引,全文索引等。這里由于主要介紹BTree索引和B+Tree索引,我們平時(shí)使用最多的InnoDB引擎就是基于B+Tree索引的。
目前版本的MySQL InnoDB引擎已經(jīng)支持全文索引,但不支持中文,可以通過(guò)使用ngram插件開(kāi)始支持中文。
從二叉搜索樹(shù)聊起
了解過(guò)數(shù)據(jù)結(jié)構(gòu)的朋友應(yīng)該知道一種叫二叉樹(shù)的數(shù)據(jù)結(jié)構(gòu)。二叉樹(shù)根據(jù)用途不同,衍生了不同的變種,比如堆,比如二叉搜索樹(shù)。
而二叉搜索樹(shù)中,為了防止極端情況樹(shù)的高度過(guò)大影響查詢(xún)效率,所以衍生出了一些平衡二叉查找樹(shù),最典型的就是AVL和紅黑樹(shù)。
但二叉樹(shù)在數(shù)據(jù)量較大時(shí),深度過(guò)深,不太適合數(shù)據(jù)庫(kù)的查詢(xún),所以數(shù)據(jù)庫(kù)使用了多叉樹(shù)。
BTree
BTree(又稱(chēng)為B-Tree)是一個(gè)平衡搜索多叉樹(shù)。BTree的結(jié)構(gòu)如下圖:
設(shè)樹(shù)的度為2d(d>1),高度為h,那么BTree有以下性質(zhì):
每個(gè)葉子結(jié)點(diǎn)的高度一樣,等于h;
每個(gè)非葉子結(jié)點(diǎn)由n-1個(gè)key和n個(gè)指針組成,key和指針相互隔離,結(jié)點(diǎn)兩端一定是key;
葉子結(jié)點(diǎn)指針為null;
非葉子結(jié)點(diǎn)的key都是[key,data]二元組,其中key表示作為索引的鍵,data為鍵值所在行的其它列的數(shù)據(jù);
在BTree中,對(duì)索引列是順序存儲(chǔ)的,所以很適合查找范圍數(shù)據(jù)和ORDER BY操作。
B+Tree
B+Tree是BTree的一種變種。B+Tree和BTree的不同主要在于:
B+Tree中的非葉子結(jié)點(diǎn)不存儲(chǔ)數(shù)據(jù),只存儲(chǔ)鍵值;
B+Tree的葉子結(jié)點(diǎn)沒(méi)有指針,所有鍵值都會(huì)出現(xiàn)在葉子結(jié)點(diǎn)上,且key存儲(chǔ)的鍵值對(duì)應(yīng)data數(shù)據(jù)的物理地址;
B+Tree的每個(gè)非葉子節(jié)點(diǎn)由n個(gè)鍵值key和n個(gè)指針point組成;
結(jié)構(gòu)圖:
B+Tree對(duì)比BTree的優(yōu)點(diǎn):
一般來(lái)說(shuō)B+Tree比BTree更適合實(shí)現(xiàn)外存的索引結(jié)構(gòu),因?yàn)榇鎯?chǔ)引擎的設(shè)計(jì)專(zhuān)家巧妙的利用了外存(磁盤(pán))的存儲(chǔ)結(jié)構(gòu)。
磁盤(pán)的最小存儲(chǔ)單位是扇區(qū)(sector),而操作系統(tǒng)的塊(block)通常是整數(shù)倍的sector,操作系統(tǒng)以頁(yè)(page)為單位管理內(nèi)存,一頁(yè)(page)通常默認(rèn)為4K,數(shù)據(jù)庫(kù)的頁(yè)通常設(shè)置為操作系統(tǒng)頁(yè)的整數(shù)倍,因此索引結(jié)構(gòu)的節(jié)點(diǎn)被設(shè)計(jì)為一個(gè)頁(yè)的大小,然后利用外存的“預(yù)讀取”原則,每次讀取的時(shí)候,把整個(gè)節(jié)點(diǎn)的數(shù)據(jù)讀取到內(nèi)存中,然后在內(nèi)存中查找。
已知內(nèi)存的讀取速度是外存讀取I/O速度的幾百倍,那么提升查找速度的關(guān)鍵就在于盡可能少的磁盤(pán)I/O,那么可以知道,每個(gè)節(jié)點(diǎn)中的key個(gè)數(shù)越多,那么樹(shù)的高度越小,需要I/O的次數(shù)越少,因此一般來(lái)說(shuō)B+Tree比BTree更快,因?yàn)锽+Tree的非葉節(jié)點(diǎn)中不存儲(chǔ)data,就可以存儲(chǔ)更多的key。
帶順序索引的B+Tree
一般在數(shù)據(jù)庫(kù)系統(tǒng)或文件系統(tǒng)中使用的B+Tree結(jié)構(gòu)都在經(jīng)典B+Tree的基礎(chǔ)上進(jìn)行了優(yōu)化,增加了順序訪問(wèn)指針。
在B+Tree的每個(gè)葉子節(jié)點(diǎn)增加一個(gè)指向相鄰葉子節(jié)點(diǎn)的指針,就形成了帶有順序訪問(wèn)指針的B+Tree。做這個(gè)優(yōu)化的目的是為了提高區(qū)間訪問(wèn)的性能,例如如果要查詢(xún)key為從18到49的所有數(shù)據(jù)記錄,當(dāng)找到18后,只需順著節(jié)點(diǎn)和指針順序遍歷就可以一次性訪問(wèn)到所有數(shù)據(jù)節(jié)點(diǎn),不用從頭再查詢(xún)一次,極大提到了區(qū)間查詢(xún)效率。
聚簇索引和非聚簇索引
MySQL中最常見(jiàn)的兩種存儲(chǔ)引擎分別是MyISAM和InnoDB,分別實(shí)現(xiàn)了非聚簇索引和聚簇索引。
前段時(shí)間看到一個(gè)問(wèn)題:“你知道為什么InnoDB非主鍵索引普遍比主鍵索引要慢嗎?”答案是InnoDB使用了聚簇索引,主鍵索引主需要查詢(xún)一次,而非主鍵索引需要查詢(xún)兩次。
為什么非主鍵索引需要查詢(xún)兩次呢?且看接下來(lái)的內(nèi)容。
主索引與輔助索引
首先介紹一下基礎(chǔ)的概念。在索引的分類(lèi)中,我們可以按照索引的鍵是否為主鍵來(lái)分為“主索引”和“輔助索引”,使用主鍵鍵值建立的索引稱(chēng)為“主索引”,其它的稱(chēng)為“輔助索引”。因此主索引只能有一個(gè),輔助索引可以有很多個(gè)。
為什么需要用到輔助索引?因?yàn)榍懊嫖覀兘榻B了,查詢(xún)語(yǔ)句如果想要使用索引,是需要滿足最左匹配原則的。有時(shí)候我們的查詢(xún)并不會(huì)使用到主鍵列,所以需要在其它列建立索引,即輔助索引。
非聚簇索引
非聚簇索引的主索引和輔助索引幾乎是一樣的,只是主索引不允許重復(fù),不允許空值,他們的葉子結(jié)點(diǎn)的key都存儲(chǔ)指向鍵值對(duì)應(yīng)的數(shù)據(jù)的物理地址。
非聚簇索引的數(shù)據(jù)表和索引表是分開(kāi)存儲(chǔ)的。非聚簇索引中的數(shù)據(jù)是根據(jù)數(shù)據(jù)的插入順序保存。因此非聚簇索引更適合單個(gè)數(shù)據(jù)的查詢(xún)。插入順序不受鍵值影響。
聚簇索引
聚簇索引的主索引的葉子結(jié)點(diǎn)存儲(chǔ)的是鍵值對(duì)應(yīng)的數(shù)據(jù)本身,輔助索引的葉子結(jié)點(diǎn)存儲(chǔ)的是鍵值對(duì)應(yīng)的數(shù)據(jù)的主鍵鍵值。因此主鍵的值長(zhǎng)度越小越好,類(lèi)型越簡(jiǎn)單越好。
聚簇索引的數(shù)據(jù)和主鍵索引存儲(chǔ)在一起。
聚簇索引的數(shù)據(jù)是根據(jù)主鍵的順序保存。因此適合按主鍵索引的區(qū)間查找,可以有更少的磁盤(pán)I/O,加快查詢(xún)速度。但是也是因?yàn)檫@個(gè)原因,聚簇索引的插入順序最好按照主鍵單調(diào)的順序插入,否則會(huì)頻繁的引起頁(yè)分裂(BTree插入時(shí)的一個(gè)操作),嚴(yán)重影響性能。
在InnoDB中,如果只需要查找索引的列,就盡量不要加入其它的列,這樣會(huì)提高查詢(xún)效率。
一張圖說(shuō)明聚簇索引與非聚簇索引的區(qū)別:
總結(jié)
以上是生活随笔為你收集整理的java mysql 全文索引_MySQL索引原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 从mysql数据库中读取二进制文件_数据
- 下一篇: mysql share 字体 中文_My