建立索引很簡單,但是能深入理解索引原理又能恰到好處使用索引又是另外一回事。
為什麼要給表加上主鍵?
我們平時建表的時候都會為表加上主鍵, 在某些關聯式資料庫中, 如果建表時不指定主鍵,資料庫會拒絕建表的語句執行。 事實上, 乙個加了主鍵的表,並不能被稱之為「表」。乙個沒加主鍵的表,它的資料無序的放置在磁碟儲存器上,一行一行的排列的很整齊, 跟我認知中的「表」很接近。如果給表上了主鍵,那麼表在磁碟上的儲存結構就由整齊排列的結構轉變成了樹狀結構,也就是上面說的「平衡樹」結構,換句話說,就是整個表就變成了乙個索引。
沒錯, 再說一遍, 整個表變成了乙個索引,也就是所謂的「聚集索引」。 這就是為什麼乙個表只能有乙個主鍵, 乙個表只能有乙個「聚集索引」,因為主鍵的作用就是把「表」的資料格式轉換成「索引(平衡樹)」的格式放置。
講完聚集索引 , 接下來聊一下非聚集索引, 也就是我們平時經常提起和使用的常規索引。
非聚集索引和聚集索引一樣, 同樣是採用平衡樹作為索引的資料結構。索引樹結構中各節點的值來自於表中的索引字段, 假如給user表的name欄位加上索引 , 那麼索引就是由name欄位中的值構成,在資料改變時, dbms需要一直維護索引結構的正確性。如果給表中多個字段加上索引 , 那麼就會出現多個獨立的索引結構,每個索引(非聚集索引)互相之間不存在關聯。 如下圖
每次給字段建乙個新索引, 欄位中的資料就會被複製乙份出來, 用於生成索引。 因此, 給表新增索引,會增加表的體積, 占用磁碟儲存空間。
非聚集索引和聚集索引的區別在於, 通過聚集索引可以直接查到需要查詢的資料, 而通過非聚集索引可以查到記錄對應的主鍵值 ,再使用主鍵的值通過聚集索引查詢到需要的資料,如下圖
不管以任何方式查詢表, 最終都會利用主鍵通過聚集索引來定位到資料, 聚集索引(主鍵)是通往真實資料所在的唯一路徑。
然而, 有一種例外可以不使用聚集索引就能查詢出所需要的資料, 這種非主流的方法 稱之為「覆蓋索引」查詢, 也就是平時所說的組合索引、復合索引或者多欄位索引查詢。 文章上面的內容已經指出, 當為字段建立索引以後, 欄位中的內容會被同步到索引之中,如果為乙個索引指定兩個字段, 那麼這個兩個欄位的內容都會被同步至索引之中。
先看下面這個sql語句
//這句sql語句的執行過程如下建立索引
create
index index_birthday on
user_info(birthday);
//查詢生日在2023年11月1日出生使用者的使用者名稱
select
user_name
from user_info where birthday =
'1991-11-1
'
首先,通過非聚集索引index_birthday查詢birthday等於1991-11-1的所有記錄的主鍵id值
然後,通過得到的主鍵id值執行聚集索引查詢,找到主鍵id值對就的真實資料(資料行)儲存的位置
最後, 從得到的真實資料中取得user_name欄位的值返回, 也就是取得最終的結果
我們把birthday欄位上的索引改成雙字段的覆蓋索引,
create通過非聚集索引index_birthday_and_user_name查詢birthday等於1991-11-1的葉節點的內容,然而, 葉節點中除了有user_name表主鍵id的值以外, user_name欄位的值也在裡面, 因此不需要通過主鍵id值的查詢資料行的真實所在, 直接取得葉節點中user_name的值返回即可。 通過這種覆蓋索引直接查詢的方式, 可以省略不使用覆蓋索引查詢的後面兩個步驟, 大大的提高了查詢效能,如下圖index index_birthday_and_user_name on user_info(birthday, user_name);
再詳細說下這個覆蓋索引,也叫組合索引
組合索引,即乙個索包含多個列。(當乙個表中查詢大的情況下,where條件中有多個,那麼可以使用組合查詢,不會掃瞄表,直接從索引中獲取,查詢效率高)
它遵循最左字首匹配原則,也是就是說乙個查詢可以只使用復合索引最左側的一部份。例如索引是key index (a,b,c). 可以支援a | a,b| a,b,c 3種組合進行查詢,但不支援 b,c進行查詢 .當最左側欄位是常量引用時,索引就十分有效。
因為組合索引建立的時候先對第一維排序,再對第二維,再對第三維...(非常不嚴謹的說法,但便於初學者理解)
對於如下表結構:
create那麼我們看一下下列語句:table
test(
a int,
b int,
c int,
keya(a,b,c)
);
優: select重點:如果where條件第乙個引數取範圍值,會導致索引失效(>或者《等相關範圍查詢),後面的索引也會失效。*from test where a=
10and b>
50差:
select
*from test where b =
50優:
select
*from test orderbya
差: select
*from test orderbyb
差: select
*from test orderbyc
優: select
*from test where a=
10orderbya
優: select
*from test where a=
10orderbyb
差: select
*from test where a=
10orderbyc
優: select
*from test where a>
10orderbya
差: select
*from test where a>
10order
by b //
其實會索引失效
差: select
*from test where a>
10orderbyc
優: select
*from test where a=
10and b=
10orderbya
優: select
*from test where a=
10and b=
10orderbyb
優: select
*from test where a=
10and b=
10orderbyc
優: select
*from test where a=
10and b=
10orderbya
優: select
*from test where a=
10and b>
10orderbyb
差: select
*from test where a=
10and b>
10order
by c
比如:select * from test where a>10 order by b
組合索引失效。
注:在建立多列索引時,要根據業務需求,where子句中使用最頻繁的一列放在最左邊。
1. 知乎專欄-深入淺出資料庫索引原理
2. csdn_xlxxcc-mysl單列索引和組合索引
3. csdn_工作qq感冒的石頭-mysql多個單列索引和聯合索引的區別詳解
資料庫索引的深入淺出
了不了解索引的原理,其實根據資料的大小有很大的關係,其實很多事情你會發現,資料量1萬以下不是個事情,但是如果資料量達到了1000萬之類的量級,那麼優化,查詢可能就是會成為瓶頸。所以說,很多系統都是資料量小都不是問題,資料量一大,基本上就全是問題了。說白了,索引問題就是乙個查詢問題。資料庫索引,是資料...
深入淺出理解索引
一 深入淺出理解索引結構 實際上,您可以把索引理解為一種特殊的目錄。sql server提供了兩種索引 聚集索引 clustered index,也稱聚類索引 簇集索引 和非聚集索引 nonclustered index,也稱非聚類索引 非簇集索引 下面,我們舉例來說明一下聚集索引和非聚集索引的區別...
深入淺出理解索引
一 深入淺出理解索引結構 實際上,您可以把索引理解為一種特殊的目錄。sql server提供了兩種索引 聚集索引 clustered index,也稱聚類索引 簇集索引 和非聚集索引 nonclustered index,也稱非聚類索引 非簇集索引 下面,我們舉例來說明一下聚集索引和非聚集索引的區別...