關係型數據庫的工做原理(一)

 

本文從"數據庫是如何處理一個 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)構成大數組。

分解: oop

Fig.2 優化

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

排序 線程

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。

相關文章
相關標籤/搜索