我們最先接觸的資料庫系統,大部分都是行儲存系統。大學的時候學資料庫,老師讓我們將資料庫想象成一張**,每條資料記錄就是一行資料,每行資料報含若干列。所以我們對大部分資料儲存的思維也就是乙個複雜一點的**管理系統。我們在一行一行地寫入資料,然後按查詢條件查詢過濾出我們想要的行記錄。
大部分傳統的關係型資料庫,都是面向行來組織資料的。如 mysql,postgresql。近幾年,也越來越多傳統資料庫加入了列儲存的能力。雖然列儲存的技術在十幾年前就已經出現,卻從來沒有像現在這樣成為一種流行的儲存組織方式。
行儲存和列儲存,是資料庫底層組織資料的方式。(和文件型、k-v 型,時序型等概念不在乙個層次)
行儲存系統以行的方式來組織資料。假設現在有以下 blog 資料(大學時老師布置系統課題作業總是讓我們做乙個部落格系統,大概因為他們最先接觸的網際網路就是 bbs 吧):
[,,]
行儲存將會以下列方式將資料儲存在磁碟上。我們可以思考一下,這樣的方式利於什麼樣的儲存?(此處停頓 5 秒思考一下)它利於資料一行一行的寫入,寫入一條資料記錄時,只需要將資料追加到已有資料記錄後面即可。
行模式儲存適合 oltp(online transaction processing)系統。因為資料基於行儲存,所以資料的寫入會更快。對按記錄查詢資料也更簡單。
大部分同學會問,我們的做的系統不就是在為了這個嗎?所以我為什麼還需要列式儲存,而列式儲存又是什麼?
讓我們想象一種場景,現在不是想查詢 bob 的部落格,我想統計 bob 發表的部落格數,或是整個系統今天的部落格點讚數。如果是行儲存系統,資料庫將怎樣操作?(停頓思考 10 秒)
如圖,想統計所有點讚數,首先需要將所有行資料讀入記憶體,然後對 like_num 列做 sum 操作,從而得到結果。我們假設磁碟一次可以讀取圖中 3 個方框的資料(實際需要按 byte 來讀取),那麼這個聚合計算需要 n(n=資料量)次磁碟訪問。
同樣是上面的示例資料,我們來看列式儲存是怎樣組織資料的。
[,,]
如圖所示,列式儲存將每一列的資料組織在一起。可以思考一下這樣利於什麼呢?(停頓 5 秒)
是的,利於對於列的操作,如上面我們說到的統計所有 like_num 之和。其過程將如下:
依然假設磁碟一次可以讀取 3 個方框的資料(實際按 byte 讀取)。可以看出按列儲存組織資料的方式,只需要 1 次磁碟操作就可以完成。
在程式的世界裡,我們學會了,任何的選擇和傾向都是有代價的。空間換時間,時間換空間,一致性可用性相互平衡等。選擇列式儲存必然也有不利的一面。首先就表現在資料寫入上。
當一條新資料到來,需要將每一列儲存到對應的位置。這樣就需要多次寫磁碟操作。(當然真實的資料庫不會出現圖中」擠一擠「、」挪一挪「的情況,資料庫會將不同列資料組織在不同的地方;對於多次寫操作的問題,大部分儲存系統會通過緩衝來降低這種情況帶來的不足)
row-store
column-store
因為按一行一行寫和讀取資料,因此讀取資料時往往需要讀取那些不必要的列
可以只讀取必要的列
易於按記錄讀寫資料
對乙個乙個記錄的資料寫入和讀取都較慢
適合 oltp 系統
適合 olap 系統
不利於大資料集的聚合統計操作
利於大資料集的資料聚合操作
不利於壓縮資料
利於壓縮資料
基於列模式的儲存,天然就會具備以下幾個優點:
目前列儲存模式在很多分析型資料庫中都很常見。而且因為大資料分析型需求的增多,越來越多傳統的行儲存資料庫也加入了列儲存的模式,比如 oracle 和 sql server 都有了列儲存的特性。
之前講的 apache druid 底層資料儲存就是基於列模式。有興趣的可以回顧一下。另外 hbase 是乙個比較有代表性的列儲存模式資料庫。有時間可以來聊一聊 hbase 底層是如何儲存資料的。也可以講一講數字列的壓縮方式(大家也可以先思考一下可以如何壓縮數字列)。
系列文章:
mysql:小主鍵,大問題
mysql大資料量問題與解決
你應該知道一些其他儲存——列式儲存
時間序列資料庫(tsdb)初識與選擇(influxdb、opentsdb、druid、elasticsearch對比)
十分鐘了解apache druid(集資料倉儲、時間序列、全文檢索於一體的儲存方案)
apache druid 底層儲存設計(列儲存與全文檢索)
apache druid 的集群設計與工作流程
你應該知道的一些Linux技巧
首先,我想告訴大家,在unix linux下,最有效率技巧的不是操作圖形介面,而是命令列操作,因為命令列意味著自動化。如果你看過 你可能不知道的shell 以及 28個unix linux的命令列神器 你就會知道linux有多強大,這個強大完全來自於命令列,於是,就算你不知道怎麼去 做乙個環保主義的...
你應該知道的一些Android ADB 命令
一 裝置相關 輸出格式為 serialnumber state state 有如下幾種 列名解釋 nodevice 沒有裝置 模擬器連線 offline 表示裝置未連線成功或無響應。device 裝置已連線。注意這個狀態並不能標識 android 系統已經完全啟動和可操作,在裝置啟動過程中裝置例項就...
你應該知道的一些陣列遍歷方法
遍歷陣列的方法有很多種,傳統的有 for foreach for in for of es6 其他的還有 map reduce reduceright filter every some find es6 findindex es6 參考mdn for適用於陣列和字串 let arrorstr 1 ...