行存儲和列存儲的區別

 

一、對比行存儲和列存儲的區別前,我們先來聊下背景。假設我們用mysql做了一個商品訂單庫order, 如下

orderid name kind price kg time
1 豬肉 肉類 50 2.0 2020.01.01
2 牛肉 肉類 60 1.0 2020.01.01
3 白菜 蔬菜 6 1.0 2020.01.01

 

 

 

二、什麼叫行存儲?

舉個例子,按mysql的存儲設計,數據是按行排列到磁盤中的,比如第1行的全部字段用/分開,連續寫入到磁盤中,"1/豬肉/肉類/50/2.0/2020.01.01"在order.idb文件中的offset範圍爲1201~1250。當用戶需要查找第1筆訂單的價格,語句爲"select price from table where orderid=1",mysql必須把offset1201~1250都從磁盤中讀取出來,再從中挑選出price=50這個字段值返回。在數據量不多時,看起來並沒有什麼問題。

假設我們換個場景思考,我們是做電商的,每年產生1000億條訂單,每條訂單有50種屬性(50個字段),我們的分析師需要分析商品的平均價格,這個時候如果用mysql,就需要把1000億條全部50個字段數據都從磁盤讀取,但是隻取了其中price字段使用,因爲多讀取了49個字段的無用數據,磁盤和內存都會成爲性能瓶頸,這個操作非常低效非常慢。這個時候,就需要引入列存儲的概念了。

三、什麼叫列存儲

列存儲,顧名思義就是按列存儲,還是上面的訂單案例,假設有這麼6個文件:orderid.data,name.data,kind.data,price.data,kg.data,time.data,每個文件按順序分別存了該字段的數據。如果要取第2行數據,可以從每個單獨的列文件中獲取第2個數值,並將它們放到一起構成表的第2行。


orderid.data :"1/2/3"

name.data :"豬肉/牛肉/白菜"

kind.data :"肉類/肉類/蔬菜"

price.data :"50/60/6"

kg.data :"2.0/1.0/1.0"

time.data :"2020.01.01/2020.01.01/2020.01.01"


在這種場景下,假設我們的分析師需要分析商品的平均價格,這個時候只需讀取price.data的全部內容,再做運算即可。這個操作相對mysql而言,非常高效,避免了讀取無用數據。

四、列存儲的其他優勢

由於數據是按列存儲的,每一列的數據類型其實是一致的。這個時候就可以引入數據壓縮技術,降低對磁盤吞吐量要求。比如對有範圍的整數進行位圖化,再進行遊程編碼。對於不用類型的數據,還有各種壓縮辦法。

五、數據排序

無論如何,數據都會複製到多臺機器,避免一臺機器發生故障時丟失數據。假設列存儲在生成副本時,使用不同的數據排序條件,這樣既能達到數據冗餘的功能,也能加速不同排序條件的數據分析。

六、寫操作

面對列存儲,壓縮、排序都非常有助於加速讀取查詢,但是它們的缺點是讓寫入更困難。像mysql這種行存儲,B-tree支持了原地更新方式。但對於壓縮的列存儲是不可能的,如果要在排序表的中間插入一行,不得不重寫所有的列文件。有一種解決辦法是,借鑑LSM-tree的辦法,定期合併新插入數據和磁盤文件。

 

原文出自:https://blog.csdn.net/daiyudong2020/article/details/104665885

 

end

 

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