幾張圖看懂列式存儲

1 爲什麼要按列存儲

列式存儲(Columnar or column-based)是相對於傳統關係型數據庫的行式存儲(Row-basedstorage)來說的。簡單來說兩者的區別就是如何組織表(翻譯不好,直接抄原文了):

Ø  Row-based storage stores atable in a sequence of rows.

Ø  Column-based storage storesa table in a sequence of columns.

 

下面來看一個例子:

 

從上圖可以很清楚地看到,行式存儲下一張表的數據都是放在一起的,但列式存儲下都被分開保存了。所以它們就有了如下這些優缺點:


行式存儲

列式存儲

優點

Ø  數據被保存在一起

Ø  INSERT/UPDATE容易

Ø  查詢時只有涉及到的列會被讀取

Ø  投影(projection)很高效

Ø  任何列都能作爲索引

缺點

Ø  選擇(Selection)時即使只涉及某幾列,所有數據也都會被讀取

Ø  選擇完成時,被選擇的列要重新組裝

Ø  INSERT/UPDATE比較麻煩

注:關係型數據庫理論回顧 - 選擇(Selection)和投影(Projection)



2補充:數據壓縮

剛纔其實跳過了資料裏提到的另一種技術:通過字典表壓縮數據。爲了方面後面的講解,這部分也順帶提一下了。

下面中才是那張表本來的樣子。經過字典表進行數據壓縮後,表中的字符串才都變成數字了。正因爲每個字符串在字典表裏只出現一次了,所以達到了壓縮的目的(有點像規範化和非規範化Normalize和Denomalize)



3查詢執行性能

下面就是最牛的圖了,通過一條查詢的執行過程說明列式存儲(以及數據壓縮)的優點:



關鍵步驟如下:

1.     去字典表裏找到字符串對應數字(只進行一次字符串比較)。

2.     用數字去列表裏匹配,匹配上的位置設爲1。

3.     把不同列的匹配結果進行位運算得到符合所有條件的記錄下標。

4.     使用這個下標組裝出最終的結果集。



DremelImpala的學習引申出了SQL查詢的並行執行問題,於是藉此機會深入學習一下關係數據庫以及關係代數的並行計算。

SpeedupScaleup

Speedup指用兩倍的硬件換來一半的執行時間。Scaleup指兩倍的硬件換來同等時間內執行兩倍的任務。但往往事情不是那麼簡單,兩倍的硬件也會帶來其他問題:更多CPU帶來的長啓動時間和通信開銷,以及並行計算帶來的數據傾斜問題。


多處理器架構

共享內存:任意CPU都能訪問任意的內存(全局共享)和磁盤。優點是簡單,缺點是擴展性差,可用性低。


共享磁盤:任意CPU都能訪問任何的磁盤,但是隻能訪問自己的主存。優點是可用性和擴展性比較好,缺點是實現複雜以及潛在的性能問題。


不共享:任意CPU都只能訪問自己的主存和磁盤。優點也是擴展性和可用性,缺點是實現複雜以及複雜均衡。


混合型:系統整體上是shared nothing架構,但結點內部可能是其他架構。這樣就混合了多種架構的優點。


數據分區

數據分區的目的就是:讓數據庫能夠並行地讀寫數據,最大程度地挖掘I/O的潛力。常見的分區算法有:round-robin、範圍索引、哈希。


關係運算並行化

關係代數自身的屬性允許關係操作的並行化


並行查詢處理主要分爲四步:

Ø  翻譯:將關係代數表達式翻譯成查詢樹。

Ø  優化:重排join順序,並選擇不同join算法來最小化執行開銷。

Ø  並行:將查詢樹轉換成物理操作樹,並加載到處理器。

Ø  執行:並行運行最終的執行計劃。

首先將一條SQL語句翻譯成查詢樹。


然後根據表大小、索引等情況,重新排列join順序,並選擇合適的算法。


關於join算法,常見的有以下幾種:

Ø  Nested Loop join:思路很簡單,相當於兩層循環遍歷,外層是驅動表,返回滿足關聯條件的行。適用於驅動表小(經過條件過濾後),而被驅動表上join字段有索引的情況。在兩表都很大時效率很差。

for each row R1 in the outer table
    for each row R2 in the inner table
        if R1 joins with R2
            return (R1, R2)

Ø  Sort-merge join:思路也很簡單,就是按join字段排序,然後進行歸併排序。當join字段存在重複值時,相當於每個重複值形成了一個分區。Join字段是否排序和重複值的多少決定了sort-merge的效率。適用於兩表都很大的情況,尤其當join字段上存在聚集索引時(相當於已經排好序了),效率很高。算法主要消耗在磁盤上。

Ø  Hash join:類似於存在重複值情況時的sort-merge,只不過是人爲的使用哈希函數進行分區。思路是掃描小表建立哈希表(build階段,小表也叫build),然後逐行掃描大表進行比較(probe階段,大表也叫probe)。適用於兩表都很大又沒有索引的情況,限制是只適用於等值連接。算法主要消耗在CPU上。


此外,對於子查詢還有semi joinanti join等算法。

 

最後將查詢樹變成物理操作樹,也就是真正的執行計劃。然後根據集羣的資源情況,調度到合適的結點上進行並行計算。


參考資料

1 Parallel Query Processing



五大存儲模型


昨天跟一同事討論Sybase是不是關係型數據庫,同事說Sybase是列式存儲,應該屬於NoSQL,我一直的記憶Sybase是關係型數據庫,後來專門去查了資料,才發現同事所說的Sybase IO是列式存儲;而我說的是Sybase SQL Server,是關係型數據庫。網上看到這篇文章,算是對幾種數據庫模型補補課。

數據庫市場需要細分,行式數據庫不再滿足所有的需求,而有很多需求需要通過本內存數據庫和列式數據庫解決,列式數據庫在數據分析、海量存儲、BI這三個領域有自己獨到。

1. 關係型數據庫(行式數據庫) MySQL Sybase Oracle

定義:關係模型使用記錄(行或者元祖)進行存儲,記錄存儲在表中,表由架構界定。表中的每個列都有名稱和類型,表中的所有記錄都要符合表的定義。SQL是專門的查詢語言,提供相應的語法查找符合條件的記錄,如表聯接(Join)。表聯接可以基於表之間的關係在多表之間查詢記錄。

存儲格式:行式數據庫把一行中的數據值串在一起存儲起來,然後再存儲下一行的數據,以此類推。

例如以下的一個表:


EmpIdLastnameFirstnameSalary
1SmithJoe40000
2JonesMary50000
3JohnsonCathy44000




 

1,Smith,Joe,40000;2,Jones,Mary,50000;3,Johnson,Cathy,44000;

特點:據以行相關的存儲體系架構進行空間分配,主要適合與小批量的數據處理,常用於聯機事務型數據處理。不能滿足後面三個需求:對數據庫高併發讀寫要求,對海量數據的高效率存儲和訪問需求,對數據庫高可擴展性和高可用性。 一句話不適合分佈式、高併發和海量。

2. 列式存儲 Sybase IQ, C-Store, Vertica,Hbase

定義:什麼是列式數據庫?列式數據庫是以列相關存儲架構進行數據存儲的數據庫。列式存儲以流的方式在列中存儲所有的數據,主要適合與批量數據處理和即席查詢。

存儲格式 :

列式數據庫把一列中的數據值串在一起存儲起來,然後再存儲下一列的數據,以此類推。

1,2,3;Smith,Jones,Johnson;Joe,Mary,Cathy;40000,50000,44000;

特點:包括查詢快,由於查詢需要讀取的blocks少;數據壓縮比高,正因爲同一類型的列存儲在一起。Load快。 簡化數據建模的複雜性。但是插入更新慢,不太適合數據老是變化,它是按列存儲的。這時候你就知道它適做DSS(決策支持系統),BI的優秀選擇,數據集市,數據倉庫,它不適合OLTP。

Examples are Sybase IQ, C-Store, Vertica, VectorWise,MonetDB, ParAccel, and Infobright.

具體請參考如下地址:http://en.wikipedia.org/wiki/Column-oriented_DBMS.

3. 鍵值存儲 Cassandra, Hbase, Bigtable

即Key-Value存儲,簡稱KV存儲。它是NoSQL存儲的一種方式。它的數據按照鍵值對的形式進行組織,索引和存儲。KV存儲非常適合不涉及過多數據關係業務關係的業務數據,同時能有效減少讀寫磁盤的次數,比SQL數據庫存儲擁有更好的讀寫性能。

典型例子 Sorted String Table即SSTable。其實STL 庫中map和hash_map, JAVA中hash_table, hash_map就是鍵值存儲。 但是他們值只支持內存操作,而且map的查詢效率太低,關鍵是他們只是簡單的數據結構,不能實現較大規模存儲和分佈式,而且數據的修改效率比較低。 而SSTalbe就解決了這些問題。

鍵值存儲實際是分佈式表格系統的一種。

分佈式key-value 系統有cassandra, hbase, bigtable etc

注:其實Hbase也屬於列式存儲

4. 文檔存儲

文檔存儲支持對結構化數據的訪問,不同於關係模型的是,文檔存儲沒有強制的架構

事實上,文檔存儲以封包鍵值對的方式進行存儲。在這種情況下,應用對要檢索的封包採取一些約定,或者利用存儲引擎的能力將不同的文檔劃分成不同的集合,以管理數據。

與關係模型不同的是,文檔存儲模型支持嵌套結構。例如,文檔存儲模型支持XML和JSON文檔,字段的“值”又可以嵌套存儲其它文檔。文檔存儲模型也支持數組和列值鍵。

與鍵值存儲不同的是,文檔存儲關心文檔的內部結構。這使得存儲引擎可以直接支持二級索引,從而允許對任意字段進行高效查詢。支持文檔嵌套存儲的能力,使得查詢語言具有搜索嵌套對象的能力,XQuery就是一個例子。MongoDB通過支持在查詢中指定JSON字段路徑實現類似的功能。

MongoDB 對SQL 和ACID 支持的比較全面的數據庫了。不過, 比較多的還是介紹日誌的採集和存儲,小文件的分佈式存儲,類似互聯網微博應用的數據存儲等方面的內容。

 

5.圖形數據庫

圖形數據庫存儲頂點和邊的信息,有的支持添加註釋。

圖形數據庫可用於對事物建模,如社交圖譜、真實世界的各種對象。IMDB(Internet MovieDatabase)站點的內容就組成了一幅複雜的圖像,演員與電影彼此交織在一起。

圖形數據庫的查詢語言一般用於查找圖形中斷點的路徑,或端點之間路徑的屬性。Neo4j是一個典型的圖形數據庫。


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