本文介紹向量化引擎實踐案例與常見問題。
實踐案例
以下所有案例,需要在指定的數據庫中創建插件(polar_csi)并啟用向量化引擎功能,詳細的功能開啟及語法說明請參考開啟和使用向量化引擎。
案例一:寬表模式中對指定列的統計分析
寬表模式下,一張表擁有數十個列甚至上百個列,但查詢負載中只需要統計/分析部分列,此時可以使用加速索引進行加速。
以一張包含24個列的widecolumntable表為例,包含BIGINT
、DECIMAL
、TEXT
、JSONB
、TEXT[]
等類型,現要對其中的id_1,domain,consumption,start_time和end_time等五個列進行統計分析,統計每個客戶在過去一年多個domain里消費的金額。
創建一張名為widecolumntable表,表格結構定義如下,然后按照您的需求插入測試數據。
CREATE TABLE widecolumntable ( id_1 BIGINT NOT NULL PRIMARY KEY, id_2 BIGINT, id_3 BIGINT, id_4 BIGINT, id_5 BIGINT, id_6 BIGINT, version INT, domain TEXT, consumption DECIMAL(18,3), c_level CHARACTER varying(1) NOT NULL, priority BIGINT, operator TEXT, notify_policy TEXT, call_id UUID NOT NULL, provider_id BIGINT NOT NULL, name_1 TEXT NOT NULL, name_2 TEXT NOT NULL, name_3 TEXT, start_time TIMESTAMP WITH TIME ZONE NOT NULL, end_time TIMESTAMP WITH TIME ZONE NOT NULL, comment JSONB NOT NULL, description TEXT[] NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL, updated_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL );
將id_1,domain,consumption,start_time和end_time列加入到加速索引中。
CREATE INDEX idx_wide_csi ON widecolumntable USING CSI(id_1, domain, consumption, start_time, end_time);
統計過去一年客戶在不同domain中消費金額,并按消費額進行排序。
SET polar_csi.exec_parallel to 4; SET polar_csi.scan_parallel to 4; SELECT id_1, domain,SUM(consumption) FROM widecolumntable WHERE start_time > '20230101' and end_time < '20240101' GROUP BY id_1, domain Order By SUM(consumption);
測試結果:在一億條數據規模和4并行度模式下,采用向量化引擎+加速索引方式的性能為PostgreSQL原生并行執行的30倍。
查詢語句
PostgreSQL原生并行
向量化引擎+加速索引
Q1
243 s
7.9 s
案例二:為分區表創建加速索引
在PostgreSQL中,分區表是應對數據不斷增長的有效手段,會通過分區裁剪來加速查詢。PolarDB PostgreSQL版向量化引擎也支持分區表,能夠進一步應對分區表的統計和分析需求。
本案例中,會創建一個多級分區表,并模擬插入3.2億條數據(約16 GB),之后根據分區條件進行統計分析。
創建名為sales的多級分區表,以時間列sale_date作為分區鍵,定義如下。
CREATE TABLE sales ( sale_id serial, product_id int NOT NULL, sale_date date NOT NULL, amount numeric(10,2) NOT NULL, primary key(sale_id, sale_date) ) PARTITION BY RANGE (sale_date); CREATE TABLE sales_2023 PARTITION OF sales FOR VALUES FROM ('2023-1-1') TO ('2024-1-1') PARTITION BY RANGE (sale_date); CREATE TABLE sales_2023_a PARTITION OF sales_2023 FOR VALUES FROM ('2023-1-1') TO ('2023-7-1'); CREATE TABLE sales_2023_b PARTITION OF sales_2023 FOR VALUES FROM ('2023-7-1') TO ('2024-1-1'); CREATE TABLE sales_2024 PARTITION OF sales FOR VALUES FROM ('2024-1-1') TO ('2025-1-1') PARTITION BY RANGE (sale_date); CREATE TABLE sales_2024_a PARTITION OF sales_2024 FOR VALUES FROM ('2024-1-1') TO ('2024-7-1'); CREATE TABLE sales_2024_b PARTITION OF sales_2024 FOR VALUES FROM ('2024-7-1') TO ('2025-1-1');
生成數據并寫入到分區表,約16 GB。
INSERT INTO sales (product_id, sale_date, amount) SELECT (random()*100)::int AS product_id, '2023-01-1'::date + i/3200000*7 AS sale_date, (random()*1000)::numeric(10,2) AS amount FROM generate_series(1, 320000000) i;
為表創建加速索引,將sale_id,product_id,sale_date和amount字段加入到加速索引。
CREATE INDEX ON sales USING CSI(sale_id, product_id, sale_date, amount);
查詢。根據不同的分區條件生成三條查詢語句,為Q1,Q2和Q3。
SET polar_csi.enable_query to on; SET polar_csi.exec_parallel to 4; SET polar_csi.scan_parallel to 4; SET max_parallel_workers_per_gather to 4; -- Q1 EXPLAIN ANALYZE SELECT sale_date, COUNT(*) FROM sales WHERE sale_date BETWEEN '2023-1-1' and '2023-3-1' AND amount > 100 GROUP BY sale_date; -- Q2 EXPLAIN ANALYZE SELECT sale_date, COUNT(*) FROM sales WHERE sale_date BETWEEN '2023-1-1' and '2023-9-1' AND amount > 100 GROUP BY sale_date; -- Q3 EXPLAIN ANALYZE SELECT sale_date, COUNT(*) FROM sales WHERE sale_date BETWEEN '2023-1-1' and '2024-3-1' AND amount > 100 GROUP BY sale_date;
測試結果:4并行度模式下,向量化引擎在三條查詢語句中都比原生PostgreSQL并行執行快25倍以上。
查詢語句
PostgreSQL原生并行
向量化引擎+加速索引
Q1
9.29 s
0.26 s
Q2
29.19 s
1.03 s
Q2
48.30 s
2.02 s
案例三:與 OSS 結合構建低成本歷史數據查詢與分析方案
PolarDB PostgreSQL版冷熱分層存儲可以將歷史數據轉儲到OSS中,這類數據每天訪問頻次較低,主要用于數據歸檔與分析使用。PolarDB PostgreSQL版向量化引擎支持與冷熱分層存儲的結合,用戶可以方便地分析存儲在OSS中的冷數據。
本案例在案例二的基礎上,展示如何將分區表以及對應的加速索引轉儲到冷存中。
使用前提:集群已經開啟冷數據分層存儲功能,開啟冷數據分層存儲功能請參考開啟和使用冷數據分層存儲。
創建polar_osfs_toolkit插件。
CREATE EXTENSION IF NOT EXISTS polar_osfs_toolkit;
將sales表的所有子分區以及對應的加速索引都轉儲到OSS中。
SELECT polar_alter_subpartition_to_oss_with_indexes('sales',0);
查看子分區表sales_2023_a的信息,表空間為OSS。
查詢,無需更改查詢語句。
SET polar_csi.enable_query to on; SET polar_csi.exec_parallel to 4; SET polar_csi.scan_parallel to 4; SET max_parallel_workers_per_gather to 4; -- Q1 EXPLAIN ANALYZE SELECT sale_date, COUNT(*) FROM sales WHERE sale_date BETWEEN '2023-1-1' and '2023-3-1' AND amount > 100 GROUP BY sale_date; -- Q2 EXPLAIN ANALYZE SELECT sale_date, COUNT(*) FROM sales WHERE sale_date BETWEEN '2023-1-1' and '2023-9-1' AND amount > 100 GROUP BY sale_date; -- Q3 EXPLAIN ANALYZE SELECT sale_date, COUNT(*) FROM sales WHERE sale_date BETWEEN '2023-1-1' and '2024-3-1' AND amount > 100 GROUP BY sale_date;
除了手動將分區表數據轉儲到OSS之外,還可以結合pg_cron插件自動化將歷史分區表數據轉儲到OSS。詳細案例請參考分區表按時間線自動冷存。
案例四:將分析后的數據寫入到新的表
在很多統計類的查詢負載中,會將分析后的數據保存到其他結果表中。
PolarDB PostgreSQL版向量化引擎支持INSERT INTO SELECT
和CREATE TABLE AS SELECT
語句,可以在一條SQL語句中,利用向量化引擎高效分析并將結果寫入到結果表中。
利用
CREATE TABLE AS SELECT
將案例一的統計結果轉到新的表中。SET polar_csi.exec_parallel to 4; SET polar_csi.scan_parallel to 4; CREATE TABLE result_table AS SELECT id_1, domain,SUM(consumption) FROM widecolumntable WHERE start_time > '20230101' and end_time < '20240101' GROUP BY id_1, domain Order By SUM(consumption);
利用
INSERT INTO SELECT
將案例一的統計結果插入到已有的表中。CREATE TABLE result_table(id_1 BIGINT, domain TEXT, sum DECIMAL(18,3)); INSERT INTO result_table SELECT id_1, domain,SUM(consumption) as sum FROM widecolumntable WHERE start_time > '20230101' and end_time < '20240101' GROUP BY id_1, domain Order By SUM(consumption);
常見問題
與PolarDB ePQ的關系
PolarDB PostgreSQL版的ePQ是基于云原生一寫多讀架構下,為了充分利用所有RO節點的計算資源而研發的跨機并行能力。其能夠將一個查詢語句分發到所有的RO節點執行,而開源PostgreSQL的并行能力只能使用一個節點的計算資源,因此PolarDB PostgreSQL版的ePQ比開源PostgreSQL具有更好的scale out能力。
PolarDB PostgreSQL版的向量化引擎與ePQ并非同一種技術,向量化引擎的目標是在同樣的硬件資源下算得更快,而ePQ的目標是能充分利用數據庫集群的所有資源,二者是相互補充的關系。
與開源PostgreSQL的關系
向量化引擎不侵入開源PostgreSQL,只是作為PostgreSQL的一個索引,如果不需要性能加速,刪除索引即可,不影響PostgreSQL中已有的基礎數據。后續會納入到PolarDB PostgreSQL版開源版本中。
查詢無法使用向量化引擎加速
請按如下步驟檢查:
查看表是否創建加速索引。
查看所涉及的列是否都在加速索引中。
是否開啟向量化查詢,執行
SET polar_csi.enable_query = ON
開啟向量化引擎功能。polar_csi.cost_threshold
過大,查詢語句會被PostgreSQL原生執行引擎處理,可以將該值調小。如果還無法使用向量化引擎加速,可執行
SET client_min_messages = debug5
來進一步排查。
創建索引時的錯誤消息
錯誤一: ERROR: access method "csi" does not exist
需要創建polar_csi
插件,請執行以下指令。
CREATE EXTENSION polar_csi;
錯誤二: ERROR: function polar_csi_trigger_func() does not exist
search_path
設置錯誤導致無法創建polar_csi_trigger_func
,請執行以下指令。
SET search_path = 'public';