1. 程式人生 > >(轉載)列式儲存與行式儲存

(轉載)列式儲存與行式儲存

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.     使用這個下標組裝出最終的結果集。

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

Speedup和Scaleup

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)。表聯接可以基於表之間的關係在多表之間查詢記錄。

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

例如以下的一個表:

EmpId Lastname Firstname Salary
1 Smith Joe 40000
2 Jones Mary 50000
3 Johnson Cathy 44000
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是一個典型的圖形資料庫。