全部產品
Search
文件中心

AnalyticDB:字典編碼

更新時間:Jun 08, 2024

雲原生資料倉儲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_namen_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_name列是一系列國家的名字,是固定範圍的字串集合,適合使用字典編碼。

n_regionkey

integer

LZ4編碼或int編碼

整型資料,預設使用LZ4編碼或int編碼。

n_comment

character varying(152)

字典編碼

n_comment列包含不重複的字串資料,當資料行數超過編碼閾值(255)後,n_comment列將不會使用字典編碼,而是嘗試使用LZ4編碼。

字典編碼支援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