資料庫索引,小白連環16問
這段時間一直在面試,問了很多候選人資料庫索引相關的知識,能答好的不是很多,令人惋惜啊,我也想留你啊……
面試官:瞭解過資料庫索引嗎?
候選人:聽過一些,底層資料結構好像是二叉樹,不對,好像是 B 樹,哦,我想起來了,好像是 B+樹……(像極了當年面試的我)
面試官:聽過雜湊索引嗎?
候選人:我知道雜湊表,雜湊索引沒聽過
面試官:今天面試先到這裡了,回去等訊息吧……
溫馨提示:本文是資料庫索引的簡單入門篇,後面會透過圖解的方式逐步帶大家深入索引的原理,敬請期待!
先引入一個簡單的示例,透過示例操作解釋一下為什麼需要資料庫索引。
假設我們有一個名為 t_employee 的資料庫表,這個資料庫表有三列:name,age,address,資料量有上萬行。
如果我們想要查詢所有名為「leixiaoshuai」員工的詳細資訊,只需要寫一個簡單的 SQL 語句就可以搞定,相信大家都會寫。
SELECT * FROM t_employee
WHERE name = 'leixiaoshuai'
如果沒有索引,會發生什麼?
一旦我們執行了這條 SQL 查詢語句,在資料庫內部是如何工作的呢?資料庫會搜尋 t_employee 表中的每一行,從而確定員工的名字(name)是否為 ‘leixiaoshuai’。由於我們想要得到每一個名字為 leixiaoshuai 的僱員資訊,在查詢到第一個符合條件的行記錄後,不能停止查詢,因為可能還有其他符合條件的行。所以,必須一行一行的查詢直到最後一行,這就意味資料庫不得不檢查上萬行資料才能找到所有名字為 leixiaoshuai 的員工。這就是所謂的全表掃描。
資料庫索引如何幫助提高效能?
你可能會想:「這麼簡單的查詢語句居然還需要全表掃描,資料庫也太笨了吧?!」
這就類似於用人眼從頭到尾逐字逐句讀一本書,效率太低了!
那應該怎麼辦?聰明的你肯定想到解決方案了:「加個索引啊」。
這就是索引派上用場的時候了,使用索引的目的就是**透過減少表中需要檢查的記錄/行的數量來加速搜尋查詢。**說的再簡單點:「索引就是用來加速查詢的」。
什麼是索引?
那麼問題來了,什麼是索引呢?索引本質是一種資料結構(最常見的是 B+樹),是在表的列上建立的。
索引的資料結構是什麼樣的?
常見MySQL索引一般分為:Hash索引和**B+**樹索引,InnoDB引擎中預設的是B+樹。
B+樹 是最常用於索引的資料結構,時間複雜度低:查詢、刪除、插入操作都可以可以在 logn 時間內完成。另外一個重要原因儲存在 B+樹 中的資料是有序的。
在B+樹常規檢索場景下,從根節點到葉子節點的搜尋效率基本相當,不會出現大幅波動,而且基於索引的順序掃描時,也可以利用雙向指標快速左右移動,效率非常高。
雜湊索引就是採用一定的雜湊演算法,把鍵值換算成新的雜湊值,檢索時不需要類似B+樹那樣從根節點到葉子節點逐級查詢,只需一次雜湊演算法即可立刻定位到相應的位置,速度非常快。
雜湊表索引是如何工作的?
如果你在建立索引時指定資料結構為「雜湊表」,那這些索引也可稱為「雜湊索引」。
雜湊索引的優點非常明顯,在一定場景下,檢索指定值時雜湊表的效率極高。比如上面我們討論的一個查詢語句:SELECT * FROM t_employee WHERE name = ‘leixiaoshuai’,如果在 name 列上加一個雜湊索引,檢索速度有可能會成倍提升。
哈系索引的工作方式是將列的值作為索引的鍵值(key),鍵值相對應實際的值(value)是指向該表中相應行的指標。因為雜湊表基本上可以看作是關聯陣列,一個典型的資料項就像 「leixiaoshuai => 0x996996」,而 0x996996 是對記憶體中表中包含 leixiaoshuai 這一行的引用。在哈系索引的中查詢一個像 leixiaoshuai 這樣的值,並得到對應行的在記憶體中的引用,明顯要比掃描全表獲得值為 leixiaoshuai 的行的方式快很多。
雜湊索引的缺點
上面說了雜湊索引的優點,那雜湊索引的缺點也是繞不過去的。
雜湊表是無順的資料結構,對於很多型別的查詢語句雜湊索引都無能為力。舉例來說,假如你想要找出所有小於40歲的員工。你怎麼使用使用雜湊索引進行查詢?這不可行,因為雜湊表只適合查詢鍵值對,也就是說查詢相等的查詢(例:like “WHERE name = ‘leixiaoshuai’)。雜湊表的鍵值對映也暗示其鍵的儲存是無序的。這就是為什麼雜湊索引通常不是資料庫索引的預設資料結構,因為在作為索引的資料結構時,其不像B+Tree那麼靈活。
總結一下缺點:
(1)不支援範圍查詢 (2)不支援索引完成排序 (3)不支援聯合索引的最左字首匹配規則
還有什麼其他型別的索引?
常見的還有:R 樹和點陣圖索引。
R 樹通常用來為空間問題提供幫助。例如,一個查詢要求“查詢出所有距離我兩公里之內的麥當勞”,如果資料庫表使用R樹索引,這類查詢的效率將會提高。
點陣圖索引(bitmap index), 這類索引適合放在包含布林值(true 和 false)的列上。
索引如何提高效能?
因為索引基本上是用來儲存列值的資料結構,這使查詢這些列值更加快速。如果索引使用B+樹資料結構,那麼其中的資料是有序的,有序的列值可以極大的提升效能。
假如我們在 name 這一列上建立一個 B+樹 索引,這意味著當我們用之前的SQL查詢name=‘leixiaoshuai‘時不需要再掃描全表,而是用索引查詢去查詢名字為‘leixiaoshuai’的員工,因為索引已經按照按字母順序排序。索引已經排序意味著查詢一個名字會快很多,因為名字少字母為‘L’的員工都是排列在一起的。另外重要的一點是,索引同時儲存了表中相應行的指標以獲取其他列的資料。
資料庫索引中到底存的是什麼?
你現在已經知道資料庫索引是建立在表的某列上的,並且儲存了這一列的所有值。但是需要理解的重點是資料庫索引並不儲存這個表中其他列(欄位)的值。舉例來說,如果我們在 name 列建立索引,那麼 age 列和 address 列上的值並不會儲存在這個索引當中。如果我們確實把其他所有欄位也儲存在個這個索引中,那這樣會佔用太大的空間而且會十分低效。
索引還儲存指向錶行的指標
如果我們在索引裡找到某一條記錄作為索引的列的值,如何才能找到這一條記錄的其它值呢?
這很簡單,資料庫索引同時儲存了指向表中的相應行的指標。指標是指一塊記憶體區域, 該記憶體區域記錄的是對硬碟上記錄的相應行的資料的引用。因此,索引中除了儲存列的值,還儲存著一個指向在行資料的索引。也就是說,索引中的name這列的某個值(或者節點)可以描述為 (“leixiaoshuai”, 0x996996), 0x996996 就是包含 “leixiaoshuai”那行資料在硬碟上的地址。如果沒有這個引用,你就只能訪問到一個單獨的值(“leixiaoshuai”),而這樣沒有意義,因為你不能獲取這一行記錄的employee的其他值-例如地址(address)和年齡(age)。
資料庫如何知道何時使用索引?
當你執行一條查詢 SQL 語句時,資料庫會檢查在查詢的列上是否有索引。假設 name 列上確實建立了索引,資料庫會接著檢查使用這個索引做查詢是否合理 ,因為有些場景下,使用索引比起全表掃描會更加低效。
可以強制資料庫在查詢中使用索引嗎?
通常來說, 你不會告訴資料庫什麼時候使用索引,資料庫自己決定。
如何在SQL中建立索引?
下面是在前面示例中的Employee_Name列上建立索引時實際SQL的外觀:
CREATE INDEX name_index
ON t_employee (name)
如何在SQL中建立聯合(多列)索引?
我們可以在age 和 address 兩列上建立聯合索引,SQL如下:
CREATE INDEX age_address_index
ON t_employee (age, address)
可以把資料庫索引類比成什麼?
一個非常好的類比是把資料庫索引看作是書的索引。
你從頭到尾逐字逐行讀完就是「全表掃描」;
你翻看目錄挑選感興趣的部分閱讀就是走了索引。
使用資料庫索引有什麼代價?
既然索引優點這麼多,那給所有列加上索引不就完事了,no no no,加索引是有代價的。
(1)索引會佔用空間。你的表越大,索引佔用的空間越大。
(2)在更新操作有效能損失。當你在表中新增、刪除或者更新行資料的時候, 在索引中也會有相同的操作。
基本原則是:如果表中某列在查詢過程中使用的非常頻繁,那就在該列上建立索引。
參考:
How do database indexes work? And, how do indexes help? Provide a tutorial on database indexes.
資料庫索引漫談
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024420/viewspace-2925175/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 小白也能懂的Mysql資料庫索引詳解MySql資料庫索引
- 資料庫索引分裂 問題分析資料庫索引
- 教小白搭建sybase資料庫環境資料庫
- 資料庫索引資料庫索引
- 資料庫表的唯一索引問題資料庫索引
- python環境連結Oracle資料庫PythonOracle資料庫
- [資料庫]索引失效資料庫索引
- indexedDB 資料庫 索引Index資料庫索引
- 資料庫索引原理資料庫索引
- 【Mysql】資料庫索引,百萬資料測試索引效果MySql資料庫索引
- 4解3連環(16)
- openGauss資料庫JDBC環境連線配置(Eclipse)資料庫JDBCEclipse
- 玩轉資料庫索引資料庫索引
- 概覽資料庫索引資料庫索引
- 資料庫的部分索引資料庫索引
- 資料庫索引層級資料庫索引
- mysql資料庫的索引MySql資料庫索引
- 資料庫之建立索引資料庫索引
- MySQL資料庫之索引MySql資料庫索引
- 資料庫鎖的12連問,抗住!資料庫
- Django資料庫連線丟失問題Django資料庫
- 兄弟連go教程(16)資料 - ArrayGo
- 資料庫索引選擇策略資料庫索引
- mongodb資料庫如何建立索引?MongoDB資料庫索引
- 資料庫——對索引的理解資料庫索引
- 資料庫索引的工作原理資料庫索引
- MySQL資料庫索引簡介MySql資料庫索引
- 將資料庫中資料匯入至solr索引庫資料庫Solr索引
- [20181128]toad連線資料庫的問題.txt資料庫
- 用Navicat連線資料庫-資料庫連線(MySQL演示)資料庫MySql
- 資料庫索引背後的資料結構資料庫索引資料結構
- 連線資料庫資料庫
- idea內建資料庫DataGrip + 索引Idea資料庫索引
- SAP中的資料庫表索引資料庫索引
- H2資料庫文件索引資料庫索引
- 武林內功,資料庫的索引資料庫索引
- MySQL 資料庫-索引注意事項MySql資料庫索引
- 資料庫索引融會貫通資料庫索引