什麼是“列式存儲”,一篇文章讓你“秒懂”


導讀:在講《Apache Druid 底層存儲設計》時就說過要講一講列式存儲。現在來了,通過本文你可以瞭解到行存儲模式、列存儲模式、它們的優缺點以及列存儲模式的優化等知識。

從數據存儲講起

我們最先接觸的數據庫系統,大部分都是行存儲系統。大學的時候學數據庫,老師讓我們將數據庫想象成一張表格,每條數據記錄就是一行數據,每行數據包含若干列。所以我們對大部分數據存儲的思維也就是一個複雜一點的表格管理系統。我們在一行一行地寫入數據,然後按查詢條件查詢過濾出我們想要的行記錄。

大部分傳統的關係型數據庫,都是面向行來組織數據的。如 Mysql,Postgresql。近幾年,也越來越多傳統數據庫加入了列存儲的能力。雖然列存儲的技術在十幾年前就已經出現,卻從來沒有像現在這樣成為一種流行的存儲組織方式。

行存儲和列存儲,是數據庫底層組織數據的方式。(和文檔型、K-V 型,時序型等概念不在一個層次)

行存儲

行存儲系統以行的方式來組織數據。假設現在有以下 blog 數據(大學時老師佈置系統課題作業總是讓我們做一個博客系統,大概因為他們最先接觸的互聯網就是 BBS 吧):

<code>[
  {
    "title": "Oriented Column Store",
    "author": "Alex",
    "publish_time": 1508423456,
    "like_num": 1024
  },{
    "title": "Apache Druid",
    "author": "Bob",
    "publish_time": 1504423069,
    "like_num": 10
  },{
    "title": "Algorithm",
    "author": "Casey",
    "publish_time": 1512523069,
    "like_num": 16
  }
]/<code>
什麼是“列式存儲”,一篇文章讓你“秒懂”

行存儲將會以下列方式將數據存儲在磁盤上。我們可以思考一下,這樣的方式利於什麼樣的存儲?(此處停頓 5 秒思考一下)它利於數據一行一行的寫入,寫入一條數據記錄時,只需要將數據追加到已有數據記錄後面即可。

行模式存儲適合 OLTP(Online Transaction Processing)系統。因為數據基於行存儲,所以數據的寫入會更快。對按記錄查詢數據也更簡單。

大部分同學會問,我們的做的系統不就是在為了這個嗎?所以我為什麼還需要列式存儲,而列式存儲又是什麼?

讓我們想象一種場景,現在不是想查詢 Bob 的博客,我想統計 Bob 發表的博客數,或是整個系統今天的博客點贊數。如果是行存儲系統,數據庫將怎樣操作?(停頓思考 10 秒

什麼是“列式存儲”,一篇文章讓你“秒懂”

如圖,想統計所有點贊數,首先需要將所有行數據讀入內存,然後對 like_num 列做 sum 操作,從而得到結果。我們假設磁盤一次可以讀取圖中 3 個方框的數據(實際需要按 byte 來讀取),那麼這個聚合計算需要 N(N=數據量)次磁盤訪問。

這種經常需要通過大量數據集來聚合統計數據的需求其實是 OLAP 系統的常見行為。基於這個需求我們也可以明白為什麼這幾年列式存儲開始流行。因為數據,大數據,數據分析,也就是 OLAP(Online Analytical Processing)在線分析系統的需求增多了,數據寫入的事務和按記錄查詢數據都不是它的關注點,它關注的是數據過濾,統計。

列存儲

同樣是上面的示例數據,我們來看列式存儲是怎樣組織數據的。

<code>[
  {
    "title": "Oriented Column Store",
    "author": "Alex",
    "publish_time": 1508423456,
    "like_num": 1024
  },{
    "title": "Apache Druid",
    "author": "Bob",
    "publish_time": 1504423069,
    "like_num": 10
  },{
    "title": "Algorithm",

    "author": "Casey",
    "publish_time": 1512523069,
    "like_num": 16
  }
]/<code>
什麼是“列式存儲”,一篇文章讓你“秒懂”

如圖所示,列式存儲將每一列的數據組織在一起。可以思考一下這樣利於什麼呢?(停頓 5 秒

是的,利於對於列的操作,如上面我們說到的統計所有 like_num 之和。其過程將如下:

什麼是“列式存儲”,一篇文章讓你“秒懂”

依然假設磁盤一次可以讀取 3 個方框的數據(實際按 byte 讀取)。可以看出按列存儲組織數據的方式,只需要 1 次磁盤操作就可以完成。

在程序的世界裡,我們學會了,任何的選擇和傾向都是有代價的。空間換時間,時間換空間,一致性可用性相互平衡等。選擇列式存儲必然也有不利的一面。首先就表現在數據寫入上。

什麼是“列式存儲”,一篇文章讓你“秒懂”

當一條新數據到來,需要將每一列存儲到對應的位置。這樣就需要多次寫磁盤操作。(當然真實的數據庫不會出現圖中”擠一擠“、”挪一挪“的情況,數據庫會將不同列數據組織在不同的地方;對於多次寫操作的問題,大部分存儲系統會通過緩衝來降低這種情況帶來的不足)


對比

什麼是“列式存儲”,一篇文章讓你“秒懂”

列存儲優勢

基於列模式的存儲,天然就會具備以下幾個優點:

  • 自動索引 因為基於列存儲,所以每一列本身就相當於索引。所以在做一些需要索引的操作時,就不需要額外的數據結構來為此列創建合適的索引。
  • 利於數據壓縮 利於壓縮有兩個原因。一來你會發現大部分列數據基數其實是重複的,拿上面的數據來說,因為同一個 author 會發表多篇博客,所以 author 列出現的所有值的基數肯定是小於博客數量的,因此在 author 列的存儲上其實是不需要存儲博客數量這麼大的數據量的;二來相同的列數據類型一致,這樣利於數據結構填充的優化和壓縮,而且對於數字列這種數據類型可以採取更多有利的算法去壓縮存儲。

最後

目前列存儲模式在很多分析型數據庫中都很常見。而且因為大數據分析型需求的增多,越來越多傳統的行存儲數據庫也加入了列存儲的模式,比如 Oracle 和 Sql Server 都有了列存儲的特性。

之前講的 Apache Druid 底層數據存儲就是基於列模式。有興趣的可以回顧一下。另外 HBase 是一個比較有代表性的列存儲模式數據庫。有時間可以來聊一聊 HBase 底層是如何存儲數據的。也可以講一講數字列的壓縮方式(大家也可以先思考一下可以如何壓縮數字列)。


作者:MageByte
鏈接:https://juejin.im/post/5e8e8b7651882573b0473de2


分享到:


相關文章: