資深架構師關於數據庫管理系統索引技術的概述

數據庫管理系統索引技術概述

2018年4月23日 Wray Zheng9

文章目錄

  • 爲什麼需要索引?

  • 索引中的一些概念

  • 索引如何提高查詢效率?

  • 索引的分類

  • 稀疏索引與稠密索引

  • 主索引與輔助索引

  • 聚簇索引和非聚簇索引

  • 總結

爲什麼需要索引?

我們知道,磁盤的讀寫效率是比較低的,以傳統機械硬盤爲例,讀寫時涉及到讀寫頭的尋道和定位,這部分時間開銷可能比實際讀寫數據時所花的時間還要長。即使是固態硬盤,由於數據的存儲可能是散落在各個磁盤塊中,通過指針連接起來,因此訪問數據時需要對磁盤進行多次讀寫,同樣會帶來效率上的問題。

再來看數據庫的存儲,數據庫中的一個表可能存儲在多個文件中,而每個文件包含了多個磁盤塊(扇區),我們討論最好的情況,也就是所有記錄都是按查詢的字段進行排序,那麼此時可以利用二分法等高效的算法進行搜索。如果是在內存中進行這種搜索,log(n) 的時間確實非常高效,但放在磁盤中就未必了,爲什麼這麼說?

因爲這些高效算法通常都是在內存中操作的,也就是說數據都已經被加載到內存中。而一個表中包含的數據量可能很大,沒辦法將這些數據一次性裝載到內存中,因此我們需要通過多次讀寫磁盤來完成這些操作。這樣一來,磁盤本身的文件組織方式就會對算法的效率造成影響。

比如我們用二分法來查找數據,二分法是建立在數據能夠被隨機訪問的基礎上的,這樣可以計算出中間位置,並直接訪問該位置。如果磁盤塊是連續的還好,假設每條記錄定長,那麼我們可以得到中間位置的扇區號,直接訪問該扇區,從而得到目標記錄;但如果磁盤塊不連續,那麼只能通過指針進行連接,這樣我們就沒辦法直接得出中間位置的扇區號,只能從第一個磁盤塊開始,依次訪問它的下一個磁盤塊,也就是順序訪問,即使記錄是有序的,二分法也沒有用武之地,只能從頭遍歷記錄進行查找。

總結上述提到的問題,就是當數據量大的時候,數據無法被一次性加載到內存中,因此對數據的查找操作受限於文件在磁盤中的存儲方式,特別是利用指針來連接不連續磁盤塊的情況,極大影響查詢效率。

因此,我們想到了用索引來定位記錄,提高查詢的效率。

索引中的一些概念

以字典爲例,每個字及其解釋都可以看作一條記錄,這條記錄大致可分爲幾個字段:字、讀音、解釋。

我們是如何查找一個字對應的記錄呢?通過目錄。

因此目錄就相當於 索引,目錄中記錄了每個字及其對應的頁碼,相當於一個個 索引項。

我們是根據什麼來找到索引項的?對了,是字。因此字就是用於索引的字段,叫做 索引字段,頁碼相當於一條記錄的實際存儲地址,等價於指向記錄所在磁盤位置的指針。

存儲索引項的文件稱爲 索引文件,而存儲實際數據(表)的文件稱爲 主文件。

索引如何提高查詢效率?

索引的意義,就在於它只抽取了原記錄中的一部分關鍵的信息,並與記錄的位置建立關聯,以此定位記錄在磁盤上的真正位置。

索引存儲的數據較少,更容易被加載到內存中,也就意味着我們可以通過高效的算法在索引上查找目標記錄的索引項,得到目標記錄在磁盤上的位置,然後直接讀取該記錄。

例如以字段 A 作爲索引,那麼每個索引項只存 A 的值,以及 A 對應記錄所在磁盤的位置。這樣一來,我們通常可以將索引文件加載到內存中,然後根據待查詢記錄字段 A 的值,找到索引項,得到該記錄在磁盤中的位置,就能直接到特定磁盤塊將目標記錄讀取出來。

索引的分類

稀疏索引與稠密索引

首先說說稀疏索引。

稀疏索引只包含了索引字段中一部分的值,通過這些值可以確定目標記錄的範圍,然後再到這個範圍中順序查找。因此,稀疏索引要求主文件必須按照索引字段進行排序,通常索引文件本身也有相同的排序關係。

1、具有1-5工作經驗的,面對目前流行的技術不知從何下手,需要突破技術瓶頸的。
2、在公司待久了,過得很安逸,但跳槽時面試碰壁。需要在短時間內進修、跳槽拿高薪的。
3、如果沒有工作經驗,但基礎非常紮實,對java工作機制,常用設計思想,常用java開發框架掌握熟練的。
4、覺得自己很牛B,一般需求都能搞定。但是所學的知識點沒有系統化,很難在技術領域繼續突破的。
5. 以上幾點有需要的可以加羣諮詢 羣號:582100479 備註好信息!
6.阿里Java高級大牛直播講解知識點,分享知識,多年工作經驗的梳理和總結,帶着大家全面、科學地建立自己的技術體系和技術認知

資深架構師關於數據庫管理系統索引技術的概述

下面會講到主索引,它是一種特殊的稀疏索引,它的索引項並不是指向記錄,而是指向記錄所在的存儲塊。也就是說,一個存儲塊對應一個索引項。

再來說說稠密索引。

稠密索引,顧名思義,就是索引項非常稠密,到什麼程度呢?每個索引字段的值都對應一個索引項。

如果索引字段沒有重複值,那麼索引和記錄就是一一對應的關係:

資深架構師關於數據庫管理系統索引技術的概述

如果索引字段包含重複的值,有三種索引策略。

一是索引中包含重複值:

資深架構師關於數據庫管理系統索引技術的概述

此時索引項和記錄也是一一對應的關係。

二是索引中不包含重複值,主文件按索引字段排序:

資深架構師關於數據庫管理系統索引技術的概述

因爲索引字段值相同的記錄是連續放在一起的,因此索引項只需指向索引字段值相同記錄中的第一條記錄。

三是索引中不包含重複值,主文件不按索引字段排序:

資深架構師關於數據庫管理系統索引技術的概述

這裏引入了一箇中間層。因爲主文件中索引字段值存在重複,並且沒有按照索引字段排序,因此必須對每條記錄建立一個索引,才能由索引文件找到主文件中的記錄。但是由於索引中不包含重複值,因此我們可以引入一箇中間層,讓索引項不直接指向記錄,而是指向中間層。中間層的指針桶與記錄一一對應,並且索引字段值相同的記錄對應的指針桶是連續存放的,這樣就等價於中間層是按索引字段進行排序。

我們來總結一下稠密索引:

  • 若索引字段不重複,則索引與記錄自然一一對應;

  • 若索引字段重複,要麼讓索引重複,這樣索引和記錄也可以一一對應;

  • 要麼索引不重複,這就要求索引指向的結構是按索引字段排序的(中間層也可以認爲是按索引字段排序),這樣纔可以僅僅指向索引字段值相同記錄中的第一條記錄。

主索引與輔助索引

主索引通常是針對每個存儲塊建立一個索引項,索引項的個數與存儲表所佔的磁盤塊數相同。

存儲表中位於每一存儲塊的第一條記錄稱爲錨記錄,或稱爲塊錨。

資深架構師關於數據庫管理系統索引技術的概述

主索引和主文件通常都是按照索引字段進行排序,如前面所說,主索引是稀疏索引。

輔助索引是稠密索引,它是建立在一個或多個非排序字段上的輔助存儲結構,通常不同的索引字段值對應一個索引,如果有重複的索引字段值,則用類似鏈表的結構來存儲具有相同索引字段值記錄的位置,也就是前面提到的引入中間層的策略。

資深架構師關於數據庫管理系統索引技術的概述

總結和對比主索引與輔助索引:

  • 主索引是稀疏索引,輔助索引是稠密索引;

  • 一個主文件只能有一個主索引,但可以有多個輔助索引;

  • 主索引通常建立在主碼/排序碼上,輔助索引建立在其它屬性上;

  • 可以利用主索引重新組織主文件數據,但不能利用輔助索引來改變主文件數據。

聚簇索引和非聚簇索引

聚簇索引 —— 索引中鄰近的記錄在主文件中也是鄰近存儲的;

非聚簇索引 —— 索引中鄰近的記錄在主文件中不一定是臨近存儲的。

  • 如果主文件的某一排序字段取值不唯一,那麼該字段就稱爲聚簇字段。聚簇索引通常定義在聚簇字段上;

  • 聚簇索引通常是對聚簇字段上的每一個不同值建立一個索引項;

  • 一個主文件只能有一個聚簇索引文件,但可以有多個非聚簇索引文件;

  • 主索引通常是聚簇索引,輔助索引通常是非聚簇索引;

  • 主索引/聚簇索引能夠決定記錄的存儲位置,而非聚簇索引只能用於查詢已存儲記錄的位置。

資深架構師關於數據庫管理系統索引技術的概述

總結

這篇文章對索引進行了概括性的介紹,說明了索引在數據庫查詢中的意義,並介紹了索引的幾種分類方式。

有關索引的具體實現,包括 B+ 樹索引以及散列索引,後續將會單獨進行介紹。

我特意整理了一下,裏面的技術不是靠幾句話就能講清楚,所以乾脆找朋友錄製了一些視頻,很多問題其實答案很簡單,但是背後的思考和邏輯不簡單,要做到知其然還要知其所以然。如果想學習Java工程化、高性能及分佈式、深入淺出。性能調優、Spring,MyBatis,Netty源碼分析的朋友可以加我的Java進階羣:582100479,羣裏有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給大家。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章