索引虐我千百遍,我待索引如初戀
當有人問到索引是什麼時,大家都喜歡用“書的目錄”來做類比,沒有索引的數據庫,就像是沒有目錄的書,想找第3章的第7小節,就要一頁一頁翻過去,最可怕的是翻到了還要把這本書翻完才算完;那反之有索引的數據庫,就是有目錄的書了,直接按目錄找到就可以了。
書放個目錄,人來翻找,那數據庫是怎麼“翻找”呢?“目錄”又是怎麼放的?
先來看看“目錄”是怎麼放的。
數據庫在安裝完成之後,安裝程序會自動創建master、model、tempdb等幾個特殊的”系統數據庫“,其中master是數據庫的主數據庫,用于保存和管理其它系統數據庫、用戶數據庫以及數據庫的系統信息。
master中有一個名為sysindexes的系統表,專門管理索引。數據庫查詢數據表的操作都必須用到它,毫無疑義,它是本文主角之一。
PS:查看一張表的索引屬性,可以在查詢分析器中使用以下命令:select * from sysindexes where id=object_id('tablename') 。參數tablename為被索引的表名。
所以,我們現在有了一個認知:索引是專門放在一張表裡的,且放的位置和其他數據表不一樣。
那數據庫”翻找“就是先去找索引再去找數據不就行了?沒那麼簡單。先來介紹兩個概念:聚集索引、非聚集索引
- 聚集索引,是索引表的順序和對應數據表順序相同,如索引表按照ID這個字段排序,則對應數據表也一緻。
- 非聚集索引,是索引表順序和對應數據表不一緻,它指定的是邏輯順序,那數據表呢,就是按照插入順序排序的。
根據兩者的特性,也很容易總結出他們的優缺點,即聚集索引查找速度更快,缺點則是對表進行修改速度較慢,因為要保持數據順序一緻,非聚集索引則反之。他們的适用場景如下:
接下來介紹一下平衡樹
再回歸到“目錄”,在我們知道知道第3章第7節在236頁時,你可能會随便翻,但更科學的方法的:先翻到書大概二分之一的地方,再在二分之一的書裡找下一個二分之一,以此類推,直到找到正确的頁數,熟悉算法的同學會發現,這是常見的”二分法“,微軟在官方教程MOC裡另有一種說法:叫B樹(Balance Tree),即平衡樹。
索引的實現就使用了B 樹的數據結構,B 樹内把真實的數據又放在了葉子節點中,非葉子節點中隻存放了索引的數據,保證了數據項盡可能的多。
(B和B 樹的區别在于,B 樹的非葉子結點隻包含導航信息,不包含實際的值,所有的葉子結點和相連的節點使用鍊表相連,便于區間查找和遍曆。)
在對這兩個概念有認知的基礎下,我們來聊聊 數據庫是怎麼“翻找”的。
通過一個非聚集索引的訪問案例來闡述。
假定在 name 這一參數上建立了非聚集索引,則執行如下語句時,查詢過程是:
Select * From Member Where name='張三'
最後我們再來聊聊索引的優缺點吧
- 數據庫查詢INDID值為2,意味着表中存在非聚集索引頁;
- 立即從根出發,在非葉級節點中定位最接近”張三“的值“李四”,并查到其位于葉級頁面的第61頁;
- 僅在葉級頁面的第61頁的”李四“下搜尋”張三“的RID,其RID顯示為N∶706∶4,表示name字段中名為”張三“的記錄位于堆的第707頁的第4行
- 根據上述信息,數據庫立馬在堆的第 707頁第4行将該記錄“揪”出來并顯示于前台(客戶端)。視表的數據量大小,整個查詢過程費時從百分之幾毫秒到數毫秒不等。
索引有一些先天不足:
- 建立索引,系統要占用大約為表的1.2倍的硬盤和内存空間來保存索引。
- 更新數據的時候,系統必須要有額外的時間來同時對索引進行更新,以維持數據和索引的一緻性——這就如同圖書館要有專門的位置來擺放索引櫃,并且每當庫存圖書發生變化時都需要有人将索引卡片重整以保持索引與庫存的一緻。
當然建立索引的優點也是顯而易見的:在海量數據的情況下,如果合理的建立了索引,則會大大加強數據庫執行查詢、對結果進行排序、分組的操作效率。
實踐表明,不恰當的索引不但于事無補,反而會降低系統性能。因為大量的索引在進行插入、修改和删除操作時比沒有索引花費更多的系統時間。比如在如下字段建立索引應該是不恰當的:1、很少或從不引用的字段;2、邏輯型的字段,如男或女(是或否)等。
綜上所述,提高查詢效率是以消耗一定的系統資源為代價的,索引不能盲目的建立,必須要有統籌的規劃,一定要在“加快查詢速度”與“降低修改速度”之間做好平衡,有得必有失,此消則彼長。這是考驗一個DBA是否優秀的很重要的指标。
,
更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!