本文來自OPPO互聯網技術團隊,轉載請註名做者。同時歡迎關注咱們的公衆號:OPPO_tech,與你分享OPPO前沿互聯網技術及活動。數據庫
自03年開始,大數據三駕馬車紛至沓來,同志們第一次擁有了分佈式計算存儲能力。apache
這種暴發戶式的轉變, 讓人們莫名有了十足的底氣:併發
「數據量大什麼的怕你呀,數據格式什麼的, 趕忙放進來就是了;別管了,就就就那個csv吧,快糙猛搞起來呀,大不了讀的時候再解析校驗啥的,讀時校驗(schema on read)有木有」
然而計算機的世界畢竟是機器的世界,你好懂了,機器就很差懂了。存儲查詢應用的效率的問題終於仍是浮出了水面,大數據存儲格式的進化之旅由此展開。app
文本存儲很直接的問題就是存儲效率不好,而解決這個問題第一直覺就是:那用zip,snappy壓一壓行不行?分佈式
存儲可能行了,查詢就不行了,由於大部分壓縮格式一上,數據就變得不可分割了,那對應的mapper就只有一個,這併發起不來,分佈式再牛逼也白搭呀。工具
那腫麼解決呢,方法總比問題多,要不:那我把數據每隔多少條壓成一個文件,多個文件這不就天生能夠多併發了嗎?佈局
但是萬萬沒想到有個問題叫作hdfs小文件過多的問題。大數據
這這這逼出絕招啊:那把多個小文件合併怎麼樣!優化
好比下圖所示:每10w行數據進行壓縮,而後合併,並在文件頭記錄這些壓縮塊的偏移量。ui
SequenceFile的核心思想思想差很少如此,數據分塊進行組織,塊內能夠採用壓縮的方式。但它在每一個塊間設置一個同步標識用於分割塊,而沒有記錄偏移量信息。
Hive誕生之初,就以數倉工具的身份屹立大數據動物圈。而數倉面向的OLAP場景和關係數據庫面向的OLTP場景最大的區別就在於:
因此關係數據庫一般用B+tree精確索引或者Cache的方式加快查詢。
所以按列進行連續存儲的方式比按行將數據值串在一塊兒連續存儲的方式更合適於OLAP場景。
核心緣由在於:
而RCFile正是把列存的思想引入大數據的先驅者,以下圖所示。
它的基本思想是將數據水平切分紅一個個行組(row group,一般爲一個hdfs block大小), 在每一個行組內除了元數據和行組切分標識外,就是按照列值進行一波編碼再對全部列進行壓縮。
通常而言先驅者下場都不會太好,RCFile沒有擺脫這個魔咒。
其實回看歷史,緣由也很顯然:比起傳統數倉中的列存而言,RCFile粗糙的不行不行的,要學就學全套呀!hive的開發者們總結其核心問題在於:
因而乎得出結論:得改!
ORCFile也是在這個背景下,接過RCFile的大旗,應運而生,以下圖所示。
從總體結構而言,也是將數據先進行水平切分紅一個個stripe(其實和行組的概念是同樣的),但在文件末尾(filefooter)加入了對每一個行切分的偏移信息以及一些統計信息(某列的最大值最小值等等)。
偏移量的存在使得數據切分時,不用像rcfile那樣遍歷分散在整個文件中的同步標識肯定每一個stripe。而只須要讀入文件尾部的幾KB的數據,固然這也使ORC失去了追加寫的能力。
另外一方面統計信息的存在也使得數據的直接過濾掉某些stripe,好比假設有個查詢:select a from table where b < 1
那麼就能夠只讀取每一個stripe的最大最小值,從而過濾掉那些b的最小值都大於等於1的stripe,從而減少記錄的加載條數。
而在stripe內部,記錄了列的類型,並根據列的類型進行編碼。好比針對string的字典編碼,可變長度的整型編碼等等,都進一步增強了數據的存儲效率。
parquet的結構和ORCFile很相似,主要的不一樣集中在對複雜結構的表示上,這裏就不過多介紹了。
自此之後,列存的風吹遍了整個大數據生態圈。
carbondata採用多維排序的方式優化數據的列式佈局,druid在列存之上,對維度列採用directory編碼加bitmap索引的方式加速了對維度列的篩選和聚合.....
然而存儲查詢效率遠不是大數據所有,實際中的應用問題一樣重要。
19年4月,databrick公司平地一聲雷,重磅開源的delta lake,給數據添加了acid特性,支持數據的併發讀寫存儲的故事又要拉開一張大幕,世界就是這樣精彩。