混合负载透明路由
混合查询负载支持多种路由模式:自动路由、强制列存、强制行存,通过设置htap_router_mode='auto'、'column'、'row'来选择。
数据准备
创建一个包含几行数据的小表(test_small)以及包含3千行数据的大表(test_large)并插入数据。小表执行行存扫描更快,大表执行列存扫描更快。
示例:
htapdb=# CREATE TABLE test_small (
id int,
dept_id int,
salary int,
name varchar(20),
comments varchar(30)) DISTRIBUTE BY HASH(id);
CREATE TABLE
htapdb=# INSERT INTO test_small VALUES (1, 1, 1000, 'Jack', 'AAAA');
INSERT 0 1
htapdb=# INSERT INTO test_small VALUES (2, 4, 2000, 'Sam', 'BBBB');
INSERT 0 1
htapdb=# INSERT INTO test_small VALUES (3, 2, 3000, 'Sara', 'CCCC');
INSERT 0 1
htapdb=# INSERT INTO test_small VALUES (4, 6, 4000, 'Oulu', 'DDDD');
INSERT 0 1
htapdb=# INSERT INTO test_small VALUES (5, 3, 5000, 'John', 'EEEE');
INSERT 0 1
htapdb=# CREATE TABLE test_large (
id int,
dept_id int,
salary int,
name varchar(20),
comments varchar(30))DISTRIBUTE BY HASH(id);
CREATE TABLE
htapdb=# INSERT INTO test_large VALUES (generate_series(1,15000), 1, 1000, 'large', 'large table');
INSERT 0 15000
--对表test_small整表创建IMCV。
htapdb=# ALTER TABLE test_small COLVIEW;
ALTER TABLE
--对表test_large部分列创建IMCV。
htapdb=# ALTER TABLE test_large COLVIEW(id,dept_id);
ALTER TABLE 自动路由模式
通过设置htap_router_mode的值为'auto',可开启自动路由模式。自动路由模式可根据相关表、列是否创建IMCV,以及行列计划代价高低,自动选择行、列、行列混合执行计划。
示例:
htapdb=# SET htap_router_mode = 'auto';
SET
htapdb=# SHOW htap_router_mode;
htap_router_mode
------------------
auto
(1 row)
--行存计划代价更低,选择行存计划。
htapdb=# EXPLAIN (COSTS OFF) SELECT * FROM test_small;
QUERY PLAN
------------------------------
Streaming (type: GATHER)
Node/s: All datanodes
-> Seq Scan on test_small
(3 rows)
--列存计划代价更低,选择列存计划。
htapdb=# EXPLAIN (COSTS OFF) SELECT id,dept_id FROM test_large;
QUERY PLAN
---------------------------------------
Row Adapter
-> Vector Streaming (type: GATHER)
Node/s: All datanodes
-> Imcv Scan on test_large
(4 rows)
--查询目标列未创建IMCV,选择行存计划。
htapdb=# EXPLAIN (COSTS OFF) SELECT * FROM test_large;
QUERY PLAN
------------------------------
Streaming (type: GATHER)
Node/s: All datanodes
-> Seq Scan on test_small
(3 rows) 强制列存模式
以AP型负载为主的情况下,可通过设置htap_router_mode的值为'column',打开强制列存模式。该模式下,当查询相关表和列存在IMCV时,在满足列存查询的条件下,将无视代价高低,优先选择列存执行计划。
示例:
htapdb=# SET htap_router_mode = 'column';
SET
htapdb=# SHOW htap_router_mode;
htap_router_mode
------------------
column
(1 row)
--表中所有列均创建IMCV,执行列存计划。
htapdb=# EXPLAIN (COSTS OFF) SELECT * FROM test_small;
QUERY PLAN
---------------------------------------
Row Adapter
-> Vector Streaming (type: GATHER)
Node/s: All datanodes
-> Imcv Scan on test_small
(4 rows)
--查询目标列创建IMCV,执行列存计划。
htapdb=# EXPLAIN (COSTS OFF) SELECT id,dept_id FROM test_large;
QUERY PLAN
---------------------------------------
Row Adapter
-> Vector Streaming (type: GATHER)
Node/s: All datanodes
-> Imcv Scan on test_large
(4 rows)
--查询目标列未创建IMCV,执行行存扫描。
htapdb=# EXPLAIN (COSTS OFF) SELECT * FROM test_large;
QUERY PLAN
------------------------------
Streaming (type: GATHER)
Node/s: All datanodes
-> Seq Scan on test_small
(3 rows) 强制行存模式
以TP型负载为主的情况下,可通过设置htap_router_mode的值为'row',打开强制行存模式。该模式下,无论是否满足列存执行计划的条件,均选择行存计划。
示例:
htapdb=# SET htap_router_mode = 'row';
SET
htapdb=# SHOW htap_router_mode;
htap_router_mode
------------------
row
(1 row)
--强制执行行存计划。
htapdb=# EXPLAIN (COSTS OFF) SELECT * FROM test_small;
QUERY PLAN
------------------------------
Streaming (type: GATHER)
Node/s: All datanodes
-> Seq Scan on test_small
(3 rows)
--强制执行行存计划。
htapdb=# EXPLAIN (COSTS OFF) SELECT id,dept_id FROM test_large;
QUERY PLAN
------------------------------
Streaming (type: GATHER)
Node/s: All datanodes
-> Seq Scan on test_large
(3 rows)
--强制执行行存计划。
htapdb=# EXPLAIN (COSTS OFF) SELECT * FROM test_large;
QUERY PLAN
------------------------------
Streaming (type: GATHER)
Node/s: All datanodes
-> Seq Scan on test_large
(3 rows) Hint指定路由模式
单条查询可使用Hint指定目标表的列存扫描执行计划,即当指定表存在列存并且加载列满足查询要求时,强制该表执行列存扫描。例如,基于Hint语法“/* + imcvscan (tbl) */”实现。
示例:
htapdb=# SET htap_router_mode = 'row';
SET
htapdb=# SHOW htap_router_mode;
htap_router_mode
------------------
row
(1 row)
--虽然行存计划代价更低,但基于Hint选择列存计划。
htapdb=# EXPLAIN (COSTS OFF) SELECT /*+imcvscan (test_small)*/ * FROM test_small;
QUERY PLAN
---------------------------------------
Row Adapter
-> Vector Streaming (type: GATHER)
Node/s: All datanodes
-> Imcv Scan on test_small
(4 rows)
--基于Hint强制选择列存计划。
htapdb=# EXPLAIN (COSTS OFF) SELECT /*+imcvscan (test_large)*/ id,dept_id FROM test_large;
QUERY PLAN
---------------------------------------
Row Adapter
-> Vector Streaming (type: GATHER)
Node/s: All datanodes
-> Imcv Scan on test_large
(4 rows)
--Hint指定表加速列不满足查询需求,选择行存计划。
htapdb=# EXPLAIN (COSTS OFF) SELECT /*+imcvscan (test_large)*/ * FROM test_large;
QUERY PLAN
------------------------------
Streaming (type: GATHER)
Node/s: All datanodes
-> Seq Scan on test_large
(3 rows)
--Hint指定test_large执行列存扫描。
htapdb=# EXPLAIN (COSTS OFF) SELECT /*+imcvscan (test_large)*/ test_small.id, test_large.dept_id FROM test_small, test_large WHERE test_small.id = test_large.id;
QUERY PLAN
----------------------------------------------------------
Row Adapter
-> Vector Streaming (type: GATHER)
Node/s: All datanodes
-> Vector Ca Hash Join
Hash Cond: (test_large.id = test_small.id)
-> Imcv Scan on test_large
-> Vector Adapter(type: BATCH MODE)
-> Seq Scan on test_small
(8 rows)
--Hint指定连接两表均执行列存扫描。
htapdb=# EXPLAIN (COSTS OFF) SELECT /*+imcvscan (test_large) imcvscan (test_small)*/ test_small.id, test_large.dept_id FROM test_small, test_large WHERE test_small.id = test_large.id;
QUERY PLAN
----------------------------------------------------------
Row Adapter
-> Vector Streaming (type: GATHER)
Node/s: All datanodes
-> Vector Ca Hash Join
Hash Cond: (test_small.id = test_large.id)
-> Imcv Scan on test_small
-> Imcv Scan on test_large
(7 rows)
htapdb=# DROP TABLE test_large;
DROP TABLE
htapdb=# DROP TABLE test_small;
DROP TABLE