前沿拓展:
數(shù)據(jù)庫(kù)索引對(duì)于程序開(kāi)發(fā)人員都不陌生。開(kāi)發(fā)系統(tǒng)時(shí),都會(huì)使用各種各種的sql語(yǔ)句,最多的就是查詢語(yǔ)句,為了提高系統(tǒng)的響應(yīng)速度或者從數(shù)據(jù)庫(kù)查詢數(shù)據(jù)更快,都會(huì)尋找查詢比較慢的SQL查詢,分析完原因之后,就會(huì)在數(shù)據(jù)表中加上索引。那什么是索引呢?
簡(jiǎn)單說(shuō)索引就像書(shū)的目錄一樣。一本1000頁(yè)的書(shū),如果你想快速找到其中的某一個(gè)知識(shí)點(diǎn),在不借助目錄的情況下,那我估計(jì)你可得找一會(huì)兒。同樣,對(duì)于數(shù)據(jù)庫(kù)的表而言,索引其實(shí)就是它的“目錄”。
索引的出現(xiàn)其實(shí)就是為了提高數(shù)據(jù)查詢的效率。
,比如你要保存的是2018年某個(gè)城市的所有人口信息,這類不會(huì)再修改的數(shù)據(jù)。
二叉搜索樹(shù)也是最經(jīng)典數(shù)據(jù)結(jié)構(gòu)了,還是上面根據(jù)身份證號(hào)查名字的例子,如果我們用二叉搜索樹(shù)來(lái)實(shí)現(xiàn)的話,示意圖如下所示:
二叉搜索樹(shù)示意圖
二叉搜索樹(shù)的特點(diǎn):每個(gè)節(jié)點(diǎn)的左兒子小于父節(jié)點(diǎn),父節(jié)點(diǎn)又小于右兒子。這樣如果你要查ID_card_n2的話,按照?qǐng)D中的搜索順序就是按照UserA -> UserC -> UserF -> User2這個(gè)路徑得到。這個(gè)時(shí)間復(fù)雜度是O(log(N))。
二叉樹(shù)搜索算法
當(dāng)然為了維持O(log(N))的查詢復(fù)雜度,你就需要保持這棵樹(shù)是平衡二叉樹(shù)。為了做這個(gè)保證,更新的時(shí)間復(fù)雜度也是O(log(N))。
樹(shù)可以有二叉,也可以有多叉。多叉樹(shù)就是每個(gè)節(jié)點(diǎn)有多個(gè)兒子,兒子之間的大小保證從左到右遞增。二叉樹(shù)是搜索效率最高的,但是實(shí)際上大多數(shù)的數(shù)據(jù)庫(kù)存儲(chǔ)卻并不使用二叉樹(shù)。其原因是,索引不止存在內(nèi)存中,還要寫(xiě)到磁盤上。
你可以想象一下一棵100萬(wàn)節(jié)點(diǎn)的平衡二叉樹(shù),樹(shù)高20。一次查詢可能需要訪問(wèn)20個(gè)數(shù)據(jù)塊。在機(jī)械硬盤時(shí)代,從磁盤隨機(jī)讀一個(gè)數(shù)據(jù)塊需要10 ms左右的尋址時(shí)間。也就是說(shuō),對(duì)于一個(gè)100萬(wàn)行的表,如果使用二叉樹(shù)來(lái)存儲(chǔ),單獨(dú)訪問(wèn)一個(gè)行可能需要20個(gè)10 ms的時(shí)間,這個(gè)查詢可真夠慢的。
為了讓查詢過(guò)程盡量少的讀磁盤,就必須讓查詢過(guò)程訪問(wèn)盡量少的數(shù)據(jù)塊。那么,我們就不應(yīng)該使用二叉樹(shù),而是要使用“N叉”樹(shù)。這里,“N叉”樹(shù)中的“N”取決于數(shù)據(jù)塊的大小。
以InnoDB的一個(gè)整數(shù)字段索引為例,這個(gè)N差不多是1200。這棵樹(shù)高是4的時(shí)候,就可以存1200的3次方個(gè)值,這已經(jīng)17億了??紤]到樹(shù)根的數(shù)據(jù)塊總是在內(nèi)存中的,一個(gè)10億行的表上一個(gè)整數(shù)字段的索引,查找一個(gè)值最多只需要訪問(wèn)3次磁盤。其實(shí),樹(shù)的第二層也有很大概率在內(nèi)存中,那么平均訪問(wèn)磁盤的次數(shù)就更少了。
N叉樹(shù)由于在讀寫(xiě)上的性能優(yōu)點(diǎn),以及適配磁盤的訪問(wèn)模式,已經(jīng)被廣泛應(yīng)用在數(shù)據(jù)庫(kù)引擎中了。
不管是哈希還是有序數(shù)組,或者N叉樹(shù),它們都是不斷迭代、不斷優(yōu)化的產(chǎn)物或者解決方案。數(shù)據(jù)庫(kù)技術(shù)發(fā)展到今天,跳表、L**樹(shù)等數(shù)據(jù)結(jié)構(gòu)也被用于引擎設(shè)計(jì)中,這里我就不再一一展開(kāi)了。
你心里要有個(gè)概念,數(shù)據(jù)庫(kù)底層存儲(chǔ)的核心就是基于這些數(shù)據(jù)模型的。每碰到一個(gè)新數(shù)據(jù)庫(kù),我們需要先關(guān)注它的數(shù)據(jù)模型,這樣才能從理論上分析出這個(gè)數(shù)據(jù)庫(kù)的適用場(chǎng)景。
截止到這里,我用了半篇文章的篇幅和你介紹了不同的數(shù)據(jù)結(jié)構(gòu),以及它們的適用場(chǎng)景,你可能會(huì)覺(jué)得有些枯燥。但是,我建議你還是要多花一些時(shí)間來(lái)理解這部分內(nèi)容,畢竟這是數(shù)據(jù)庫(kù)處理數(shù)據(jù)的核心概念之一,在分析問(wèn)題的時(shí)候會(huì)經(jīng)常用到。當(dāng)你理解了索引的模型后,就會(huì)發(fā)現(xiàn)在分析問(wèn)題的時(shí)候會(huì)有一個(gè)更清晰的視角,體會(huì)到引擎設(shè)計(jì)的精妙之處。
MySQL中,索引是在存儲(chǔ)引擎層實(shí)現(xiàn)的,索引分為主鍵索引(key)、全文索引(FULLTEXT)、普通索引(NORMAL)、空間索引(SPATIAL)、唯一索引(UNIQUE),具體詳解在下一篇介紹。
拓展知識(shí):
原創(chuàng)文章,作者:九賢生活小編,如若轉(zhuǎn)載,請(qǐng)注明出處:http://xiesong.cn/77498.html