行存儲 與 列存儲
行業業務集中焦點:
- 有效地處理海量數據
- 兼顧安全, 可靠, 完整性
- example: HBase采用列存儲, MongoDB采用文檔型的行存儲, Lexst采用二進制的行存儲
列存儲(column-based)
傳統關系型數據庫行式存儲(Row-based storage storestable in a sequence of rows)
列存儲(Column-based storage storesatable in a sequence of columns)

行式存儲下一張表的數據是放在一起的, 但列式存儲下都被分開保存了。
數據寫入對比
- 行存儲的寫入是一次完成。如果這種寫入建立在操作系統的文件系統上, 可以保證寫入過程的成功或者失敗, 數據的完整性因此可以確定。
- 列存儲由於需要把一行記錄拆分成單列保存, 寫入次數明顯比行存儲多(意味着磁頭調度次數多, 而磁頭調度需要時間, 一般在1ms ~ 10ms), 再加上磁頭需要在盤片上移動和定位話費的時間, 實際時間消耗會更大。所以, 行存儲在寫入上占有很大的優勢。
- 數據修改實際上也是一次寫入過程。區別是數據修改是對磁盤上的記錄做刪除標記。行存儲是在指定位置寫入一次, 而列存儲是將磁盤定位到多個列上分別寫入, 這個過程仍是行存儲的列數倍, so數據修改也是行存儲占優勢。
數據讀取對比
- 數據讀取時, 行存儲通常將一行數據完全讀出, 如果只需要其中幾列數據的情況, 就會存在冗余列, 出於縮短處理事件的考量, 消除冗余列的過程通常是在內存中進行的。
- 列存儲每次讀取的數據是集合的一段或者全部, 不存在冗余性問題
- 兩種存儲的數據分布。由於列存儲的每一列數據類型是同質的, 不存在二義性問題。For instance, 某列數據類型為int(整形), 那么它的數據集合一定是整形數據。這種情況使數據解析變得十分容易。相比之下, 行存儲反而要復雜不少, 因為在一行記錄中保存了多種類型的數據, 數據解析需要在多種數據類型之間頻繁轉化,而該操作很吃cpu, 增加了解析的時間。所以, 類存儲的解析過程更有利於分析大數據。
- 數據的壓縮以及更性能的讀取方面對比


優缺點
- 行存儲:
- 優點: 行存儲的寫入是一次性完成的, 消耗的時間比列存儲少, 並且能夠保證數據的完整性
- 缺點: 數據讀取過程中會產生冗余數據, 如果只看少量數據, 此影響可以忽略; 數量大可能會影響數據的處理效率
- 列存儲:
- 優點: 在讀取過程中, 不會產生冗余數據, 這對數據完整性要求不高的大數據處理領域尤為重要(i.e. 互聯網)
- 缺點: 寫入效率, 保證數據完整性上都不如行存儲
列存儲的適用場景
概念
- OLTP (OnLine TransactionProcessor) 在線聯機事務處理系統: mysql, oracle...
- OLAP (OnlLine AnalaysierProcessor) 在線聯機分析處理系統: Hive, HBase...

(1). 一般來說, 一個OLAP類型的查詢可能需要訪問幾百萬甚至幾十億個數據行, 且該查詢往往只關心少數幾個數據列, 而其他數據列對該查詢是無意義的。
(2). 很多列式數據庫還支持列族(column group[locality group]), 即將多個經常一起訪問的數據列的各個值存放在一起。如果讀取的數據列屬於相同的列族, 列式數據庫可以從相同的地方一次性讀取多個數據列的值, 避免了多個數據列的合並。列族是一種行列混合存儲模式, 這種模式能夠同時滿足OLTP和OLAP的查詢需求。
(3). 由於同一數據列的數據重復度很高, 因此, 列式數據庫壓縮時有很大的優勢.
(4). 如果每次查詢涉及的數據量較小或者大部分查詢都需要整行的數據, 列式數據庫並不適用。
行存儲與類存儲總結:
行式存儲數據庫:
- 數據是按行存儲的。
- 沒有索引的查詢使用大量I/O。一般的數據庫表都會建立索引, 通過索引加快查詢效率。
- 建立索引和物化視圖需要花費大量的時間和資源。
- 面對查詢需求, 數據庫必須被大量膨脹才能滿足需求。
列式存儲數據庫:
- 數據按列存儲, 即每一列單獨存放。
- 數據即索引。
- 只訪問查詢涉及的列, 可以大量降低系統I/O。
- 每一列有一個線程來處理, 即查詢的並發處理性能高。
- 數據類型一致, 數據特征相似, 可以高效壓縮。 比如增量壓縮, 前綴壓縮算法都是基於列存儲的類型定制的, 所以可以大幅度提高壓縮比, 有利於存儲和減少網絡輸出數據帶寬的消耗。
數據存儲格式
-
Avro Data Files
- avro是一個數據序列化系統, 它提供:
- 豐富的數據結構
- 快速可壓縮的二進制數據格式
- 存儲持久數據的文件容器
- 遠程過程調用RPC
- 簡單的動態語言結合功能
- 實現模式:
- 二進制編碼: Avro-specific 方式依賴代碼(文件)生成特定類, 並內嵌JSON Schema
- JSON編碼: Avro-generic 方式通過JSON文件動態加載Schema, 不需要編譯加載直接就可以處理新的數據源
- avro是一個數據序列化系統, 它提供:
-
Sequence Files
- 描述:
- 是Hadoop用來存儲二進制形式的key-value對而設計的一種平面文件(Flat File)
- 特點:
- 並不保證其存儲的key-value數據是按照key的某個順序存儲的, 同時不支持append操作
- 每一個key-value被看作是一條記錄(Record), 因此基於Record的壓縮策略, SequeneceFile文件可支持三種壓縮類型:
- NONE: 對records不進行壓縮
- RECORD: 僅壓縮每一個record中的value值
- BLOCK: 將一個block中的所有records壓縮在一起
- 對應的Hadoop提供的三種類型的Writer
- SequenceFile.Writer 寫入時不壓縮任何的key-value對(Record);
- SequenceFile.RecordCompressWriter 寫入時只壓縮key-value對(Record)中的value;
- SequenceFile.BlockCompressWriter 寫入時將一批key-value對(Record) 壓縮成一個Block
- 描述:
-
Parquet Files
-
描述:
- Apache Parquet is a columnar storage format available to any project in the Hadoop ecosystem, regardless of the choice of data processing framework, data model or programming language
無論數據處理框架,數據模型或編程語言的選擇如何,Apache Parquet都是Hadoop生態系統中任何項目可用的列式存儲格式
-
特點:
- 可以跳過不符合條件的數據, 只讀取需要的數據, 降低IO數據量
- 壓縮編碼可以降低磁盤存儲空間
- 只讀取需要的列, 支持向量運算, 能夠獲取更好的掃描性能
- Parquet 格式是Spark SQL 的默認數據源, 可通過spark.sql.sources.default 配置
-
-
ORC(Optimized Row Columnar) Files
-
Hadoop生態圈中的列式存儲格式, 最初產生自Apache Hive, 用於降低Hadoop數據存儲空間和加速Hive查詢速度
-
物理視圖(HDFS)

- 邏輯視圖

- 結構塊:
- block
- stripe
- row_group
- stream
- index
- data
- Row data
- fileFooter
- postscript
- 存儲結構
- orc在hdfs上存儲, 為適應hdfs區塊存儲思想會將orc文件划分為block塊
- orc的block塊大小一般和hdfs的block大小一致,通過配置(hive.exec.orc.default.block.size 默認256M) 指定
- 每個block塊中包含多個stripe, stripe大小通過參數 (hive.exec.orc.default.stripe.size 默認64M)
- 應盡量避免stripe跨hdfs: block存儲, 否則在解析stripe時會存在IO跨節點的數據請求, 從而增加系統資源開銷
- 一般orc: block塊大小是orc:stripe大小的整數倍。但是在有些情況下是會出現block塊不能被整數個stripe完整填滿, 需要關閉跨hdfs:block的數據存儲。(hive.exec.orc.default.block.padding=false)關閉塊存儲 另外需要指定最小磁盤利用空間( hive.exec.orc.block.padding.tolerance 默認0.05,例如orc:block=256M,256*0.05=12.5M),hdfs:block塊剩余磁盤空間低於此值將放棄使用
-
