雲原生資料倉儲AnalyticDB PostgreSQL版Beam儲存引擎提供的字典編碼功能,可以將低基數的字串類型資料壓縮為整型資料,提升儲存效率,加速過濾、彙總等類型查詢的效能。
注意事項
僅儲存彈性模式v7.0.x版本支援Beam字典編碼功能。
Beam字典編碼功能在儲存彈性模式v7.0.6.2版本中結束公測正式上線,該版本修複了公測中的問題,建議您儘快升級到v7.0.6.2及以上版本。
字典編碼儲存壓縮
使用資料壓縮功能可以節約表的儲存空間,並減少查詢時從磁碟讀取的資料量大小,進而減少I/O以提升查詢效能。針對不同類型的資料,合理地選擇壓縮演算法可以更好的協助您提升資料庫的效能。
AnalyticDB PostgreSQL版字典編碼壓縮僅支援字串類型。字典編碼既支援列層級壓縮,也支援表層級壓縮。
列層級使用字典編碼壓縮時,僅對指定列進行壓縮,且需要保證列的資料類型為字串類型。
表層級使用字典編碼壓縮時,滿足低基數要求的列會被壓縮。針對非字串類型的列,建表時不進行壓縮。
本文以TPC-H的nation表為例,在使用Beam儲存表的情況下,通過compresstype='gdict'指定表層級使用字典編碼壓縮,n_name和n_comment兩列都會用字典編碼進行壓縮,樣本如下。
CREATE TABLE NATION (
n_nationkey integer NOT NULL,
n_name character(25) NOT NULL,
n_regionkey integer NOT NULL,
n_comment character varying(152)
)
USING beam WITH (compresstype = 'gdict')
DISTRIBUTED by (n_nationkey);您也可以只針對指定列n_name使用字典編碼,樣本如下。
CREATE TABLE NATION (
n_nationkey integer NOT NULL,
n_name character(25) NOT NULL ENCODING (compresstype='gdict'),
n_regionkey integer NOT NULL,
n_comment character varying(152)
)
USING beam WITH (compresstype = 'lz4', compresslevel = 9)
DISTRIBUTE by (n_nationkey);在對n_name列使用壓縮編碼後,儲存的資料大小從25 Byte(character(25)類型對字串末尾補齊空格)壓縮至2 Byte,顯著減少了資料使用的儲存空間。
n_name 字串值 | 大小(Byte) | 字典值 | 壓縮編碼大小(Byte) |
ALGERIA | 25 | 0 | 2 |
ARGENTINA | 25 | 1 | 2 |
BRAZIL | 25 | 2 | 2 |
CANADA | 25 | 3 | 2 |
CHINA | 25 | 4 | 2 |
EGYPT | 25 | 5 | 2 |
ETHIOPIA | 25 | 6 | 2 |
FRANCE | 25 | 7 | 2 |
總計 | 200 | / | 16 |
字典編碼執行加速
使用字典編碼儲存後,可以進一步在執行層使用字典壓縮後的值加速查詢計算,在低基數字串過濾、彙總、排序等情境中獲得執行加速效能提升,根據SQL模式的不同,可以在執行中獲得10%至200%的效能提升。
字典編碼執行加速功能由參數adbpg_enable_encode_optimize控制,預設配置為OFF(關閉)。對於適合使用字典編碼執行加速的SQL,最佳化器會自動產生對應的最佳化計劃。例如,對於如下SQL:
SELECT
n_name,
max(n_regionkey)
FROM
nation
WHERE
n_name > 'ALGERIA'
AND n_name < 'FRANCE'
GROUP BY
n_name;使用EXPLAIN查看執行計畫,可以看到計劃中使用的編碼方法,並引入了Decode運算元進行計算過程中的解碼。
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3) (cost=76.72..78.27 rows=81 width=36)
-> GroupAggregate (cost=76.72..77.19 rows=27 width=36)
Group Key: n_name
-> Sort (cost=76.72..76.79 rows=28 width=36)
Sort Key: n_name
-> Redistribute Motion 3:3 (slice2; segments: 3) (cost=0.00..76.05 rows=28 width=36)
Hash Key: n_name
-> Decode (cost=0.00..75.50 rows=28 width=36)
Params: dictKeyIdx[1], dictID[0]
-> Seq Scan on nation (cost=0.00..75.50 rows=28 width=36)
Filter: ((ordered_encode(n_name) > ('ALGERIA'::text)::integer with dict ID 0) AND (ordered_encode(n_name) < ('FRANCE'::text)::integer with dict ID 0))
Optimizer: Postgres query optimizer
(12 rows)相比較字串類型的資料運算,字典編碼後的整型資料運算可以有效地提升查詢效能;同時最佳化器會在執行計畫中合適的位置插入Decode運算元,對儲存層讀取到的字典編碼資料進行解碼,保證執行的準確性。
使用自動壓縮編碼最佳化
Beam儲存引擎支援自適應的壓縮演算法。如果您不確定是否需要使用字典編碼壓縮,可以在表層級指定compresstype = 'auto',儲存引擎會自動選擇合適的編碼壓縮演算法。
CREATE TABLE NATION (
n_nationkey integer NOT NULL,
n_name character(25) NOT NULL,
n_regionkey integer NOT NULL,
n_comment character varying(152)
)
USING beam WITH (compresstype = 'auto')
DISTRIBUTE by (n_nationkey);對nation表使用自動壓縮編碼後,各列的編碼如下所示:
列 | 資料類型 | 編碼方法 | 說明 |
n_nationkey | integer | LZ4編碼或int編碼 | 整型資料,預設使用LZ4編碼或int編碼。 |
n_name | character(25) | 字典編碼 |
|
n_regionkey | integer | LZ4編碼或int編碼 | 整型資料,預設使用LZ4編碼或int編碼。 |
n_comment | character varying(152) | 字典編碼 |
|
字典編碼支援Delta
Beam儲存引擎包含兩部分:
用以應對即時寫入的行存格式的Delta。
用以應對批量寫入和大量掃描情境的基於PAX結構的列存格式的Base。
v7.0.2.3及以上版本的執行個體支援行列混存Base。
v7.0.4.0及以上版本的執行個體字典編碼適配行存格式Delta,提高了字典編碼的易用性。
例如,執行如下SQL,使用EXPLAIN查看執行計畫,可以看到計劃中使用Decode運算元進行計算過程中的解碼,可以提高資料處理效率及資料安全性,進而提高字典編碼的易用性。
CREATE TABLE test_auto(a int, b text)
using beam with(compresstype=auto,compresslevel=5);
INSERT INTO test_auto values (1,'adbpg1'),(2,'adbpg2'), (3, 'adbpg3'),(10,'adbpg10');
SET adbpg_enable_encode_optimize to ON;
explain SELECT * FROM test_auto WHERE b='adbpg1';
-----------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..2.04 rows=1 width=36)
-> Decode (cost=0.00..2.02 rows=1 width=36)
Params: dictKeyIdx[2], dictID[0]
-> Seq Scan on test_auto (cost=0.00..2.02 rows=1 width=36)
Filter: (encode(b) = ('adbpg1'::text)::integer with dict ID 0)
Optimizer: Postgres-based planner