GBase 8a數(shù)據(jù)庫列存壓縮機(jī)制解析

南大通用GBase 8a數(shù)據(jù)庫(gbase database)的存儲(chǔ)引擎 Express 是純列存架構(gòu),壓縮不是可選功能,而是數(shù)據(jù)寫入的標(biāo)準(zhǔn)流程。理解列存壓縮的工作原理,能幫助 DBA 和開發(fā)人員在建表時(shí)做出更好的數(shù)據(jù)類型選擇,在查詢優(yōu)化時(shí)理解 I/O 代價(jià)的構(gòu)成,在容量規(guī)劃時(shí)給出更準(zhǔn)確的磁盤估算。本文從列存的基本原理出發(fā),逐一介紹南大通用GBase 8a數(shù)據(jù)庫(gbase database)支持的編碼策略和壓縮算法,分析不同數(shù)據(jù)特征下的最優(yōu)選擇,并給出實(shí)際測量壓縮效果的方法。

一、列存與行存的壓縮差異

理解 GBase 8a的壓縮機(jī)制,首先要理解列存儲(chǔ)與行存儲(chǔ)在數(shù)據(jù)組織方式上的根本差異,因?yàn)閴嚎s效率的高低直接源于此。

行存儲(chǔ)(如 MySQL InnoDB)把一行數(shù)據(jù)的所有字段連續(xù)存放在磁盤上。這種布局對(duì) OLTP 場景友好——讀取一整行只需一次順序 I/O,但壓縮效果有限,因?yàn)橥恍兄胁煌侄蔚臄?shù)據(jù)類型、值域和重復(fù)性各不相同,很難找到統(tǒng)一的壓縮規(guī)律。

列存儲(chǔ)把同一列的所有值連續(xù)存放在一起。這個(gè)看似簡單的改變帶來了巨大的壓縮優(yōu)勢:同一列的所有值共享相同的數(shù)據(jù)類型和值域,相鄰的值往往高度相似甚至完全相同(比如?dept_id?列中大量相同的部門編號(hào),或者?status?列中只有 0/1/2 三個(gè)值),壓縮算法可以針對(duì)這種同質(zhì)性做深度優(yōu)化。

GBase 8a 的實(shí)測壓縮比通常在 3:1 到 10:1 之間,對(duì)于重復(fù)度極高的枚舉型列(如省份、狀態(tài)碼),壓縮比甚至可以超過 20:1。這意味著同樣的原始數(shù)據(jù),在 GBase 8a 中占用的磁盤空間只有 MySQL 的十分之一甚至更少,這是 MPP 分析型數(shù)據(jù)庫能處理 TB 級(jí)數(shù)據(jù)的重要基礎(chǔ)之一。

壓縮帶來的另一個(gè)隱性收益是查詢性能的提升,這一點(diǎn)常常被忽視。因?yàn)榇疟P讀取是按數(shù)據(jù)塊進(jìn)行的,壓縮后同樣大小的數(shù)據(jù)塊能裝下更多的行,意味著一次磁盤 I/O 可以讀取到更多有效數(shù)據(jù)。在磁盤 I/O 是查詢瓶頸的場景下,壓縮率越高,查詢速度往往也越快。當(dāng)然,解壓縮本身需要消耗 CPU,在 CPU 已經(jīng)成為瓶頸的場景下,壓縮率并非越高越好,需要在 I/O 節(jié)省和 CPU 消耗之間找到平衡點(diǎn)。

二、列存的兩層壓縮體系

GBase 8a 的 Express 引擎對(duì)每列數(shù)據(jù)采用兩層壓縮:第一層是編碼(Encoding),第二層是通用壓縮算法。兩層疊加后才是最終存儲(chǔ)在磁盤上的數(shù)據(jù)形態(tài)。

這種兩層設(shè)計(jì)的原因在于:編碼是針對(duì)特定數(shù)據(jù)模式的"智能變換",能把原始值轉(zhuǎn)換成更規(guī)律、更小的表示形式,為后續(xù)的通用壓縮算法提供更好的輸入;通用壓縮算法(如 LZ4、ZSTD)則負(fù)責(zé)在編碼輸出的基礎(chǔ)上做進(jìn)一步的字節(jié)級(jí)壓縮。兩者結(jié)合,比單獨(dú)使用任何一種效果都好。

第一層:編碼策略

字典編碼(Dictionary Encoding)是最常用的編碼方式,適合低基數(shù)列——即唯一值數(shù)量遠(yuǎn)小于總行數(shù)的列。字典編碼的原理是:先把列中所有出現(xiàn)過的唯一值建立一個(gè)字典(如 {0: "active", 1: "inactive", 2: "pending"}),然后把每行的值替換為對(duì)應(yīng)的字典索引(一個(gè)很小的整數(shù))。字典索引通常只需要 1~2 個(gè)字節(jié),而原始字符串可能需要 10 多個(gè)字節(jié),壓縮效果立竿見影。

status、province、dept_id、gender 這類列是字典編碼的理想對(duì)象。GBase 8a 的 Express 引擎會(huì)自動(dòng)檢測列的基數(shù),對(duì)符合條件的列自動(dòng)應(yīng)用字典編碼,不需要手動(dòng)配置。

行程編碼(Run-Length Encoding,RLE)專為有大量連續(xù)重復(fù)值的列設(shè)計(jì)。比如按時(shí)間順序排列的數(shù)據(jù)中,order_date 列往往有大量連續(xù)相同的日期(同一天的訂單聚集在一起);按部門排列的數(shù)據(jù)中,dept_id 可能有幾千行連續(xù)相同。RLE 把連續(xù)重復(fù)的值記錄為"(值, 重復(fù)次數(shù))"的形式,大量連續(xù)重復(fù)時(shí)壓縮率極高。

差值編碼(Delta Encoding)適合單調(diào)遞增或變化幅度較小的數(shù)值列,如自增 ID、時(shí)間戳序列。差值編碼存儲(chǔ)相鄰兩個(gè)值的差而非原始值。如果 order_id 從 1 連續(xù)遞增到 10 億,差值始終是 1,整列只需存儲(chǔ)起始值和"差值=1"這條信息,壓縮率接近極限。

第二層:通用壓縮算法

在編碼之后,GBase 8a 會(huì)對(duì)數(shù)據(jù)塊進(jìn)一步應(yīng)用通用壓縮算法。常見選項(xiàng)是 LZ4 和 ZSTD:LZ4 的壓縮和解壓速度極快,CPU 開銷極小,但壓縮率中等;ZSTD 的壓縮率更高,CPU 開銷相對(duì)較大,但在現(xiàn)代多核 CPU 上通常仍在可接受范圍內(nèi)。對(duì)于 I/O 密集型場景(磁盤慢、網(wǎng)絡(luò)慢),優(yōu)先選 ZSTD;對(duì)于 CPU 密集型場景(大量并發(fā)查詢),優(yōu)先選 LZ4。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容