這篇文章,裡面講到對於乙個41g大小、包含百萬條記錄的資料庫進行查詢操作,如果利用了索引,可以把操作耗時從37s降到0.2s。
那麼什麼是索引呢?利用索引可以加快資料庫查詢操作的原理是什麼呢?
資料庫提供了一種持久化的資料儲存方式,從資料庫中查詢資料庫是乙個基本的操作,查詢操作的效率是很重要的。
對於查詢操作來說,如果被查詢的資料已某種方式組織起來,那麼查詢操作的效率會極大提高。
在資料庫中,一條記錄會有很多列。如果把這些記錄按照列col1以某種資料結構組織起來,那麼列col2一定是亂序的。
因此,資料庫在原始資料之外,維護了滿足特定查詢演算法的資料結構,指向原始資料,稱之為索引。
舉例來說,在下面的圖中,資料庫有兩列col1、col2。在儲存時,按照列col1組織各行,比如col1已二叉樹方式組織。如果查詢col1中的某乙個值,利用二叉樹進行二分查詢,不需要遍歷整個資料庫。
這樣一來列col2就是亂序的。為了解決這個問題,為col2建立了索引,即把col2也按照某種資料結構(這裡是二叉樹)組織起來。這樣子查詢列col2時只需要進行二分查詢即可。
由於資料庫是儲存在磁碟上的,因此實現索引用的資料結構會儲存在磁碟上。磁碟的io是需要注意的問題。
二叉樹二叉樹是一種經典的資料結構,但是並不適合進行資料庫索引。
原因在於二叉樹中每乙個節點的度只有2,樹的深度較高。在儲存時,一般乙個節點需要一次磁碟io,樹的深度較高,查詢乙個資料需要的磁碟io次數越高,查詢需要的時間越長。
b樹b樹是二叉樹的變種,主要區別在於每乙個節點的度可以大於2,即每乙個節點可以分很多叉,大大降低了樹的深度。
上面這些特點使得b+樹的深度大大降低,並且實現了對資料的有序組織。
b+樹b+樹是對b樹的擴充套件,特點在於非葉子節點不儲存data,只儲存key。如果每乙個節點的大小固定(如4k,正如在sqlite中那樣),那麼可以進一步提高內部節點的度,降低樹的深度。
順序訪問指標的b+樹
對b+樹做了一點改變,每乙個葉子節點增加乙個指向相鄰葉子節點的指標,這樣子可以提高區間訪問的效能。
如圖,訪問key在15到30的data。
根據索引查詢資料時,分兩步
根據索引找到rowid(第一次b+樹查詢)
根據rowid查詢其他列的資料(第二次b+樹查詢)
通過兩次b+樹查詢避免了一次全表掃瞄。
下面是乙個資料庫中乙個表的統計資訊,通過sqlite3_analyzer工具得到。1. 對某一行或某幾行新增primary key或unique約束,那麼資料庫會自動為這些列建立索引
2. 指定某一列為integer primary key,那麼這一列和rowid被指定為同一列。即可以通過rowid來獲取,也可以通過列名來獲取。
可以看到表中一共有3651條記錄,b樹的深度只有2,有33個葉子節點,1個非葉子節點。因此最多隻需要2次磁碟io就可以根據rowid找到一行的資料。
比如我們有這麼乙個表
查詢語句如下
由於沒有索引,因此不得不做一次全表掃瞄。通過順序訪問指標遍歷各個記錄(record),比較fruit這一列和『peatch』是否一致,如果一致,返回這一行的price列的值。select price from fruitsforsale where fruit=『peach』
對『fruit』列加索引
如下,執行同樣的語句,可以根據索引找到目標列對應的rowid為4,然後根據rowid找到對應行,從而選出price。通過兩次b+樹查詢避免了全表查詢。這也是最簡單的情況
多條索引命中
建立索引時,不要求索引是uique的,即索引表中的key可以是一樣的。
如下圖,索引表中有orange
兩條記錄,找到第一條記錄時,根據順序訪問指標可以輕易找到下一條索引,避免另一次b+樹查詢。(rowid=1和rowid=23可能位於兩個不同的葉子節點中)
即這個查詢索引的過程,可以通過一次b+樹查和一次next操作完成,而next操作是很快的。
利用索引加快搜尋和排序
在大多情況下,我們需要同時進行查詢和排序操作,這時如果建立適當的索引,可以提高查詢效率。
比如下面表中對fruit和state兩列做了索引,執行下面的sql語句時,就不需要進行排序操作了,因為索引表是帶有順序的。
在sqlite中有乙個命令叫做explain query plan
,可以檢視sqlite是如何執行查詢操作的。下面的資料庫語句不是引言中的查詢語句,原理一樣
注意detail列。不用索引時,使用的是「scan」這個詞,即全表掃瞄。使用索引時,使用的是「search」這個詞。
對於乙個41g的表來說,進行全表掃瞄的代價顯然是很大的。
**演算法和資料結構: 十 平衡查詢樹之b樹
mysql索引背後的資料結構及演算法原理
query planning(這篇是sqlite關於索引的文件)
explain query plan
mysql單錶百萬資料記錄分頁效能優化
sqlite 復合唯一索引 SQLite索引
索引 index 是一種特殊的查詢表,資料庫搜尋引擎用來加快資料檢索。簡單地說,索引是乙個指向表中資料的指標。乙個資料庫中的索引與一本書後邊的索引是非常相似的。例如,如果您想在一本討論某個話題的書中引用所有頁面,您首先需要指向索引,索引按字母順序列出了所有主題,然後指向乙個或多個特定的頁碼。索引有助...
sqlite 復合唯一索引 SQLite 索引
索引是一種特殊的查詢表,可以使用搜尋引擎的資料庫,以加快資料檢索。簡單地說,索引是乙個指標,表中的資料。乙個資料庫中的索引是非常相似在一本書的背部的索引。例如,如果你想在一本書中引用的所有頁面討論某個話題,先參考索引,按字母順序列出所有主題,再交由乙個或多個特定的頁碼。索引有助於加快select查詢...
sqlite 復合唯一索引 SQLite 索引
sqlite 索引 index 索引 index 是一種特殊的查詢表,資料庫搜尋引擎用來加快資料檢索。簡單地說,索引是乙個指向表中資料的指標。乙個資料庫中的索引與一本書的索引目錄是非常相似的。拿漢語字典的目錄頁 索引 打比方,我們可以按拼音 筆畫 偏旁部首等排序的目錄 索引 快速查詢到需要的字。索引...