索引的本質

前言1:我會結合mysql和mssql來寫。雖然是不一樣的數據庫,可是兩者索引的本質是同樣的。mysql

前言2:業務系統大多數時間無非動態條件+排序+查找,如何提高排序查找效率乃重中之重算法

前言3:程序猿的救命稻草——建立索引sql

若是你對前言的內容感興趣(怎麼會有興趣呢,很痛苦好吧。。。)不過爲了未來數據庫

升職加薪,當上總經理,贏取白富美,走上人生巔峯

請繼續往下看吧bash

一 索引的概念

1 索引的定義數據結構

不須要太多術語,就一句話:快速查找&有序 的數據結構工具

堆表不保證有序性能

2 彙集索引和非彙集索引

彙集索引Clustered Index
1 列能夠有重複值。
2若是主鍵默認作彙集索引,則符合惟一約束.
3索引組織表是有序的,堆表是無序的。
4只能有一個
5mysql的表就是一張索引組織表,若無主鍵,InnoDB engine會自動建立一個6字節(48bit)列做爲主鍵。mssql則不會
6當select * 的時候,檢索最快,由於葉子節點有所有的數據

非彙集索引NonClustered Index
1葉子節點上保存二個信息:索引字段值,對應彙集索引鍵值(無彙集索引,則是數據位置的指針)
2select * 浪費性能,須要標籤查找。select 非彙集列 則最快複製代碼

快問快答——ui

主鍵和彙集索引有什麼區別?miemiemie~~spa

3 索引在執行計劃中的術語

結構
SCAN
SEEK
堆(沒有彙集索引的表格數據頁)
Table Scan
沒有彙集索引
彙集索引
Clustered Index Scan
有彙集索引,但也是全表掃描
Clustered index seek
用索引結果檢索Data
非彙集索引
Index Scan
有非彙集索引,只是小部分Data掃描,比整表掃描代價小得多
index seek
用索引結果檢索Data

二索引是如何創建的---- B+樹王國是如何平地而起?

1 索引是一個B+樹

B+樹的概念,網上一大堆,這裏不贅述。我用一個圖來展現B+樹是如何插入元素的。

2 索引插入算法—— 靈魂畫手



3 索引分頁三個基本類型

彙集索引結點級(非leaf),彙集索引葉級別(就是數據行),非彙集索引結點級,非彙集索引的葉級別。

下一個章節會對索引分頁詳細說明,其中彙集索引葉級別,非彙集索引結點級不作細節介紹。

三 索引的內部存儲

爲了瞭解數據內部存儲,咱們須要先知道已下幾個知識點:

1 Sqlserver 一個分頁是8k,mysql一個分頁則是16k。存儲理論是一致的。

PageType(分頁類型)
1:數據頁面;2:索引頁面;3:Lob_mixed_page;4:Lob_tree_page;10:IAM頁面
IndexID (索引ID)
0 表明堆, 1 表明彙集索引, 2-250 表明非彙集索引 ,大於250就是text或image字段
sysindexes keycnt
0堆;1惟一彙集索引;2不帶惟一彙集索引、惟一非彙集索引
接下來,是正餐:

A彙集索引的節點行(非leaf)

組成:索引鍵值+下級指針


dbcc page(test,1,162,1) --索引leafdbcc page(test,1,178,1) -- 索引節點dbcc page(test,1,898,1) --根索引複製代碼

B非彙集索引的葉級行

1 非彙集索引+堆表

組成:非彙集鍵+ RID


2非彙集索引+彙集索引

組成:非彙集鍵值+彙集鍵值


3非彙集索引+彙集索引(字段重疊)


C非彙集索引的節點行

組成:非彙集鍵值+向下指針

四 沒有靈丹妙藥——索引的代價

1 在項目中,我見過索引列數據類型是 varchar(500)的

做爲索引鍵值的列,數據類型太大
從上面能夠得知,數據頁大小是固定的.
一個索引行越長,那麼一個數據頁所能容納的索引就越少,這樣索引樹就會複雜。
查詢的時候產生的io就越多。
而數據庫的查詢處理器在選擇執行計劃的時候,若是使用索引的成本過高,那麼數據庫就會選擇全表掃描,那麼添加索引的意義在哪兒呢?複製代碼

2物理表隨意加索引

從問題1過渡過來,若是索引過多了,會怎樣呢?
有的攻城獅真的不要太大方,索引嗷嗷的加。最後索引比真正數據文件還要大。。。
索引是落磁盤的,是增長存儲壓力的。索引越多統計信息就越多,寫入會變慢。
那麼,應該怎麼加呢?
應該參考業務需求,熱點表熱點查詢加索引,爭取一個索引能夠覆蓋多個查詢。複製代碼

五經常使用索引工具

/*
* 索引實際大小
* 獲得索引名字
* Jaki Wang
*/
create function fn_Index_name(@object_id int,@index_id int)
returns sysname
as 
begin
declare @index_name sysname
select @index_name = name 
from sys.indexes 
where object_id=@object_id and index_id=@index_id
return @index_name
end複製代碼
相關文章
相關標籤/搜索