關系型數據庫的工作原理(一)


 

本文從"數據庫是如何處理一個 SQL 查詢的?"這一基本數據庫操作來討論關系數據庫的工作原理。

 

cost based optimization(基於成本的優化)

為了解成本,需要了解一下復雜度的概念,具體考慮時間復雜度,一般用O表示,對應某個算法(查詢),對於其隨着數據量的增加復雜度增加趨勢,而非具體值,O給出了一個很好的描述。時間復雜度一般用最壞時間復雜度表示,除此還有算法內存復雜度,算法I/O復雜度。

歸並排序:

歸並排序是諸多排序算法中的一種,理解歸並排序有助於之后的查詢優化以及meger join連接。

歸並(merge):

Fig.1

歸並排序的大概過程如圖1所示:把兩個長度為4(N/2)的已排序數組組合成一個有序的長度為8(N)的數組,總計算次數為8(N),即將兩個長度為N/2的數組遍歷次數。整個算法可以分為兩步:

  1. 分解:把整個大數組分解為多個小數組;
  2. 排序:幾個小數組被(按順序) 合並起來(使用 merge)構成大數組。

分解:

Fig.2

如圖2,將N維數組逐層分解為一元數組,分解次數為log(N)。

排序

Fig.3

從圖3可知,merge的次數與分解的次數是一致的,每次merge對數組元素排序的次數是相同的(N,這里是8):

Step1: 4次merge,每次對2個元素排序,共4*2次運算。

Step1: 2次merge,每次對4個元素排序,共2*4次運算。

Step1: 1次merge,每次對8個元素排序,共1*8次運算。

故排序的總運算次數為N*log(N)。

 

算法偽代碼:

array mergeSort(array a)

   if(length(a)==1)

      return a[0];

   end if

   //recursive calls

   [left_array right_array] := split_into_2_equally_sized_arrays(a);

   array new_left_array := mergeSort(left_array);

   array new_right_array := mergeSort(right_array);

   //merging the 2 small ordered arrays into a big one

   array result := merge(new_left_array,new_right_array);

   return result;

 

歸並排序的擴展:

  1. merge 時可以不必創建新數組,而是直接修改原數組,以減少內存,in_place算法即如此。
  2. 只對內存中正在處理的數據進行加載從而降低內存和磁盤占用,該類算法為external sorting。
  3. 把歸並過程在多個進程/線程/服務器上執行,這便是hadoop關鍵步驟。

     

三種重要的數據結構:

數組

數據庫中的表可以理解為數組,如圖4:

Fig.4

每行代表一個對象;

每列代表一個對象屬性,每個屬性有一個固定類型(integer, string…);

二維數組較好的抽象出了數據的存儲,但是當對數據進行過濾尤其是有多個過濾條件時,難度非常大,所以用數組抽象數據是不可取的。

樹(二叉樹/B樹)

二叉樹是一種特殊樹結構,滿足一下特點:

左子樹在整個對應分支最小,右子樹在整個對應分支最大。如圖5:

                                                   Fig.5        

這是一個簡單的B樹,共15個節點,如要找40,從根節點136開始,136>40,故查詢根節點的左子樹80,80>40,再查80的左子樹,此時40=40。

對應具體問題,如圖4,假設查詢某位員工國籍(即column3字段)是UK的,可將國籍作為樹節點進行搜索,找到節點值為UK,即可找到UK值所在的行,查詢該表中的行,得到其他信息。

B樹只需要log(N)次運算,可作為較好的索引搜索,節點存儲值的類型可以是多種類型,只要有相應類型的對比函數,就可以進行一次或多次查詢過濾。

B+樹

B樹較好的解決了等值過濾問題,但當出現范圍過濾時,就有較大麻煩,比如當要過濾圖5中兩個值之間數值時,復雜度達N,且為獲取整個值不得不加載整個樹,增加了I/O。B+樹只在最后一層節點才存儲數據,其他節點只做路由功能,如圖6.

Fig.6

可以看到B+樹的每個葉子節點都指向其后續節點,因此當查詢t->(M-t)范圍內的數據時,復雜度為M+Log(N),相比B樹N,當N很大時,B+樹顯然速度更快,且因不用遍歷整棵樹所以I/O很小。

Hash表

哈希表是一種通過元素的key快速查詢到數據元素的數據結構,當數據庫做查詢操作時,通過哈希表更快。哈希表一般有幾個部分:

  1. 給個元素定義一個key值
  2. 定義一個哈希函數,hash函數通過key找到元素位置(bucket)。
  3. 定義key值比較函數,通過key值比較函數,在找到的bucket查找對應的值。

                                                Fig.7

如圖7,共10個bucket,哈希函數是modulo,比如此時要找59,通過hash函數找到bucket9,然后在bucket9中通過key值對比函數,59!=99,經過7次運算逐值對比發現沒有59.

經上列可知,查詢復雜度與hash函數相關,hash的值越多(bucket越多),bucket含有的值越少(key值深度越小),復雜度越低,但空間占用越大,hash值越小,則相反。如果哈希函數選擇得足夠好,那么查詢的時間復雜度可以是 O(1)。

Hash與數組:

哈希表可以只將部分bucket存入內存(比如常用),其他的Bucket存入磁盤,而數組不得不分配一塊連續內存空間,尤其當數組很大時,極困難。

 

----------------------

文章為How does a relational database work筆記,參考其中文翻譯Franklin Yang。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM