是什麼影響了數據庫索引選型?

上一篇文章咱們介紹了索引背後的數據結構,這篇文章咱們來介紹影響索引數據結構選型的因素——存儲器存取。html

主存存取原理

主存的構成

主存儲器(簡稱主存或內存)包括存取體、各類邏輯部件及控制電路等。存儲體由許多存儲單元組成,每一個存儲單元又包含若干個存儲元件,每一個存儲元件能寄存一位二進制代碼「0」或「1」。這樣,一個存儲單元能夠存儲一串二進制代碼,這串二進制代碼稱爲存儲字,這串二進制代碼的位數稱爲存儲字長,能夠是8位、16位或者32位等。mysql

mark

主存與CPU的聯繫

mark

畫外音:

MAR(Memory Address Register)是存儲器地址寄存器,用來存放欲訪問的存儲單元的地址,其位數對應存儲單元的個數(若MAR爲10位,則有210=1024個存儲單元,記爲1k)。算法

MDR(Memory Data Register)是存儲器數據寄存器,用於存放從存儲體某單元取出的代碼或準備往某存儲單元存入的代碼,其位數與存儲字長相等。sql

現代計算機通常將MAR和MDR集成在CPU芯片中。數據庫

主存的存取過程

若是把存儲體看作是一棟大樓,那麼每一個存儲單元能夠當作這棟大樓裏的每一個房間,每一個存儲元能夠看作房間裏的一張牀位,牀位有人至關於「1」,無人至關於「0」。每一個房間都須要一個房間號,便於咱們找到房間的位置。一樣,能夠賦予每一個存儲單元一個編號,稱爲存儲單元的地址號數據結構

主存的工做方式就是按照存儲單元的地址號來實現對存儲字各位的存(寫入)、取(讀出)。性能

現代主存的結構和存取原理比較複雜,這裏拋卻具體差異,抽象出一個十分簡單的存取模型來講明主存的工做原理。優化

mark

主存的存取過程以下:操作系統

當系統須要讀取主存時,首先由CPU將該字的地址送到MAR,經地址總線送至主存,而後發出讀命令。主存接到讀命令後,根據地址定位到指定存儲單元,而後將此存儲單元數據放到數據總線上,供其它部件讀取。翻譯

寫主存的過程相似,若要向主存存入一個信息字時,首先CPU將該字要存入的主存單元的地址經MAR送到地址總線,並將信息字送入MDR,而後向主存發出寫命令,主存接到寫命令後,便將數據總線上的信息寫入到對應地址總線指出的主存單元中。

畫外音:實際上主存存取的過程並無這麼簡單,還須要通過通過地址譯碼(邏輯地址—>物理地址)等過程。

磁盤存取原理

mark

咱們知道,索引自己也很大,不可能所有存儲在內存中(根節點常駐內存),通常以文件形式存儲在磁盤上。那麼問題來了,索引檢索須要磁盤I/O操做。與內存不一樣,磁盤I/O存在機械運動耗費,相對於內存存取,I/O存取的消耗要高几個數量級。

磁盤的構成

磁盤的總體結構示意圖:

mark

一個磁盤由大小相同且同軸的圓形盤片組成,磁盤能夠轉動(各個磁盤必須同步轉動)。在磁盤的一側有磁頭支架,磁頭支架固定了一組磁頭,每一個磁頭負責存取一個磁盤的內容。磁頭不能轉動,可是能夠沿磁盤半徑方向運動(實際是斜切向運動),每一個磁頭同一時刻也必須是同軸的,即從正上方向下看,全部磁頭任什麼時候候都是重疊的。

磁盤盤片示意圖:

mark

盤片被劃分紅一系列同心環,圓心是盤片中心,每一個同心環叫作一個磁道,全部半徑相同的磁道組成一個柱面。磁道被沿半徑線劃分紅一個個小的段,每一個段叫作一個扇區,每一個扇區是磁盤的最小存儲單元。

磁盤的存取過程:

當須要從磁盤讀取數據時,系統會將數據邏輯地址傳給磁盤,磁盤的控制電路按照尋址邏輯將邏輯地址翻譯成物理地址,即肯定要讀的數據在哪一個磁道,哪一個扇區。

爲了讀取這個扇區的數據,須要將磁頭放到這個扇區上方,爲了實現這一點:

  1. 首先必須找到柱面,即磁頭須要移動對準相應磁道,這個過程叫作尋道,所耗費時間叫作尋道時間
  2. 而後目標扇區旋轉到磁頭下,即磁盤旋轉將目標扇區旋轉到磁頭下。這個過程耗費的時間叫作旋轉時間

因此一次訪盤請求(讀/寫)完成過程由三個動做組成:

  1. 尋道(時間):磁頭移動定位到指定磁道
  2. 旋轉延遲(時間):等待指定扇區從磁頭下旋轉通過
  3. 數據傳輸(時間):數據在磁盤與內存之間的實際傳輸

局部性原理與磁盤預讀

因爲存儲介質的特性,磁盤自己存取就比主存慢不少,再加上機械運動耗費,磁盤的存取速度每每是主存的幾百萬分之一,所以爲了提升效率,要儘可能減小磁盤I/O。爲了達到這個目的,磁盤每每不是嚴格按需讀取,而是每次都會預讀,即便只須要一個字節,磁盤也會從這個位置開始,順序向後讀取必定長度的數據放入內存。這樣作的理論依據是計算機科學中著名的局部性原理:

局部性原理: CPU訪問存儲器時,不管是存取指令仍是存取數據,所訪問的存儲單元都趨於彙集在一個較小的連續區域中。

時間局部性(Temporal Locality):若是一個信息項正在被訪問,那麼在近期它極可能還會被再次訪問。

空間局部性(Spatial Locality):在最近的未來將用到的信息極可能與如今正在使用的信息在空間地址上是臨近的。

因爲磁盤順序讀取的效率很高(不須要尋道時間,只需不多的旋轉時間),所以對於具備局部性的程序來講,預讀能夠提升I/O效率

預讀的長度通常爲頁(page)的整倍數。頁是計算機管理存儲器的邏輯塊,硬件及操做系統每每將主存和磁盤存儲區分割爲連續的大小相等的塊,每一個存儲塊稱爲一頁(在許多操做系統中,頁的大小一般爲4k),主存和磁盤以頁爲單位交換數據。當程序要讀取的數據不在主存中時,會觸發一個缺頁異常,此時系統會向磁盤發出讀盤信號,磁盤會找到數據的起始位置並向後連續讀取一頁或幾頁載入內存中,而後異常返回,程序繼續運行。

數據庫爲何選用B-/+Tree索引

以前提到過,SQL優化的一個重要原則是減小磁盤I/O次數,磁盤I/O次數也是評價索引結構的優劣的指標之一。

B-Tree分析:

根據B-Tree的定義,可知檢索一次最多須要訪問h(B-Tree的高度)個節點。數據庫系統的設計者巧妙 利用了磁盤預讀原理,將一個節點的大小設爲等於一個頁,這樣每一個節點只須要一次I/O就能夠徹底載入。可是邏輯上存儲在一個頁裏並不表明物理上也存儲在一個頁裏,爲了達到這個目的,每次新建節點時,直接申請一個頁的空間,這樣就保證一個節點物理上也存儲在一個頁裏,加之計算機存儲分配都是按頁對齊的,就實現了一個節點只需一次I/O。

B-Tree中一次檢索最多須要h-1次I/O,由於根節點會常駐內存。複雜度爲O(logdN)。通常實際應用中,出度d是很是大的數字,一般超過100,所以h很是小(一般不超過3)。因此B-Tree做爲索引結構效率是很是高的。這也是爲何數據庫不選用紅黑樹做爲索引(數據結構)的緣由,一是由於紅黑樹的高度h要大的多;二是紅黑樹節點在物理上多是單獨存儲的,沒法利用局部性原理。複雜度爲O(h),效率明顯比B-Tree差的多。

B+Tree分析:

上篇文章說過,B+Tree更適合索引。究其緣由,一是由於B+Tree內節點去掉了data域,所以能夠擁有更大的出度,擁有更好的性能;二是由於全部葉子節點造成有序鏈表,便於範圍查詢;全部的查找最終都會到葉子節點,從而保證了查詢性能的穩定

參考

推薦閱讀

MySQL——經過EXPLAIN分析SQL的執行計劃
MySQL——索引基礎
MySQL——索引優化實戰
數據庫索引背後的數據結構



                                                       -----END-----

            喜歡本文的朋友們,歡迎關注公衆號擼碼那些事,收看更多精彩內容

                                             

相關文章
相關標籤/搜索