Fixed Plan是Hologres特有的執行引擎優化方式,本文將為您介紹可以被Fixed Plan選中的SQL需要符合的條件和參數配置。
背景信息
Fixed Plan是Hologres特有的執行引擎優化方式,傳統的SQL執行要經過優化器、協調器、查詢引擎、存儲引擎等多個組件,而Fixed Plan選擇了短路徑(Short-Cut)優化執行SQL,繞過了優化器、協調器、部分查詢引擎的開銷。通過Fixed FrontEnd直接對接Fixed Query Engine,實現SQL執行效率的成倍提升,是支持高吞吐實時寫入,高并發查詢的關鍵優化方法。關于Fixed Plan的介紹請參見產品架構。
在Hologres中,默認走Fixed Plan的場景如下:
Flink實時寫入數據至Hologres。
DataWorks數據集成實時寫入數據至Hologres。
Holo Client寫入Hologres。
其余寫入場景可根據SQL進行一定的配置讓其走Fixed Plan,詳情請參見下文。
以上場景會默認保證符合條件的SQL走Fixed Plan,但是以上場景的SQL不一定都符合條件即不一定都能走Fixed Plan。
相關GUC參數
GUC列表
以下為Fixed Plan需要用到的參數配置,所有參數取值為on或者off。所有參數已經在Holo Client中默認打開,Session級別生效。
GUC名稱
適用場景
默認值
GUC變更記錄
hg_experimental_enable_fixed_dispatcher
查看實例的Fixed Plan是否打開。
支持Insert、Update、Delete、PrefixScan場景單行記錄的Fixed Plan寫入、更新、刪除、查詢。
on
不涉及。
hg_experimental_enable_fixed_dispatcher_for_multi_values
控制Insert多行記錄的Fixed Plan寫入。
說明不保證原子性,即一次性寫入多條的時候,如果沒報錯就是全部正常寫入了,如果報錯了只會報一條的錯誤,有可能全部沒寫入也有可能部分寫入了部分沒寫入,沒有寫入的部分會將錯誤反饋給上層應用端,由應用端進行重試。
on
Hologres從V1.3.35版本開始,通過該GUC支持Insert、Update、Delete多行記錄的Fixed Plan寫入、更新、刪除。
hg_experimental_enable_fixed_dispatcher_autofill_series
支持含有Serial類型列的Fixed Plan寫入。建議客戶端session級別打開。
off
Hologres從V1.3.25版本開始,該GUC參數的默認值為
on
。hg_experimental_enable_fixed_dispatcher_for_update
支持更新(UPDATE)場景的Fixed Plan更新。建議客戶端session級別打開。
off
Hologres從V1.3.25版本開始,
hg_experimental_enable_fixed_dispatcher_for_update
廢棄使用,即符合條件的UPDATE語句會默認使用Fixed Plan,但UPDATE多行記錄需要配置set hg_experimental_enable_fixed_dispatcher_for_multi_values =on
。hg_experimental_enable_fixed_dispatcher_for_delete
支持刪除(DELETE)場景的Fixed Plan刪除。建議客戶端session級別打開。
off
Hologres從V1.3.25版本開始,
hg_experimental_enable_fixed_dispatcher_for_delete
廢棄使用即符合條件的DELETE語句會默認走Fixed Plan,但DELETE多行記錄需要配置set hg_experimental_enable_fixed_dispatcher_for_multi_values =on
。hg_experimental_enable_fixed_dispatcher_for_scan
支持PrefixScan場景的Fixed Plan查詢。
說明PrefixScan是指多列主鍵,查詢條件只給前面幾列主鍵。目前不支持列存表PrefixScan場景的Fixed Plan查詢。
off
推薦從1.3.35版本開始使用。
hg_experimental_enable_bhclient_cache_on_session
支持更改緩存模式,存在以下兩種情況。
on:使用cached on session模式。
off:使用cached on fe模式。
說明cached on session和cached on fe的區別如下。
cached on session是每個連接擁有自己的Writer、Reader,單連接的吞吐更好,但啟動會更慢(每個表第一次進行讀或寫時需要有啟動時間)。
cached on fe是FE(Frontend)節點上所有連接共享Writer、Reader,連接斷開后Writer、Reader不會關閉,所以總體上沒有啟動時間。
off
不涉及。
hg_experimental_disable_fixed_planner_conflict_pk_check
控制
INSERT INTO <table_name> VALUES (...) ON CONFLICT(<column>)
語法中的column是否支持非主鍵字段。false:不支持。
true:支持。
說明該GUC參數設置為true,column支持填寫非主鍵字段,但INSERT ON CONFLICT語句實際執行時,還是按照主鍵是否重復(
ON CONFLICT(pk)
)來處理數據。
false
Hologres從V1.3至V2.1.28版本,
ON CONFLICT(<column>)
中的字段必須為主鍵字段。Hologres從V2.1.29版本開始,通過該GUC參數控制
ON CONFLICT(<column>)
中的字段是否支持非主鍵字段。
GUC使用
查看GUC是否開啟
通過show命令查看GUC是否開啟,命令語句如下。
SHOW <GUC_name>;
使用示例如下。
-- 查看實例級別是否開啟Fixed Plan SHOW hg_experimental_enable_fixed_dispatcher;
開啟GUC
session級別開啟GUC
通過
set
命令可以在session級別設置GUC參數。session級別的參數只在當前session生效,當連接斷開之后,將會失效,建議加在SQL前一起執行,語法示例如下。SET <GUC_name> = <values>;
GUC_name為GUC參數的名稱;values為GUC參數的值。
使用示例如下。
-- insert on conflict多行記錄支持Fixed Plan寫入 SET hg_experimental_enable_fixed_dispatcher_for_multi_values =on;
數據庫級別開啟GUC
通過
alter database xx set xxx
命令來設置數據庫級別的GUC參數,執行完成后在整個數據庫生效,設置完成后當前連接需要重新斷開連接才能生效。新建數據庫不會生效,需要重新手動設置,語法示例如下。ALTER database <db_name> SET <GUC_name> = <values>;
db_name為數據庫名稱,GUC_name為GUC參數的名稱,values為GUC參數的值。
使用示例如下。
--DB級別開啟fixed plan ALTER database <db_name> SET hg_experimental_enable_fixed_dispatcher =on;
數據類型要求
表的每一列都不能是MONEY或MONEY ARRAY類型。
進行DML(INSERT、UPDATE、DELETE)操作的列和進行SELECT(select的target列和where里的列都要滿足)操作的列支持的類型如下。
BOOLEAN(別名BOOL)
SMALLINT
INTEGER(別名INT或INT4)
BIGINT(別名INT8)
FLOAT(別名FLOAT4)
DOUBLE PRECISION(別名FLOAT8)
CHAR(n)
VARCHAR(n)
BYTEA
JSON和JSONB
TEXT(別名VARCHAR)
TIMESTAMP WITH TIME ZONE(別名TIMESTAMPTZ)
DATE
TIMESTAMP
DECIMAL(別名NUMERIC)
ROARINGBITMAP
TIME(Hologres V2.2版本開始支持)
TIMETZ(Hologres V2.2版本開始支持)
數組類型
boolean[]
smallint[]
int4[]
int8[]
float4[]
float8[]
char(n)[]
varchar(n)[]
text[]
INSERT場景
INSERT表達式
Fixed Plan支持以下INSERT表達式。
-- 寫入單行 INSERT INTO TABLE(col1,col2,col3..) VALUES(?,?,?..) ON conflict xxx; -- 寫入多行 INSERT INTO TABLE(col1,col2,col3..) VALUES(?,?,?..),(?,?,?..) ON conflict xxx;
說明支持使用INSERT命令寫入內部表,不支持外部表。
支持使用INSERT命令寫入分區表,Hologres V1.3及以上版本支持寫入分區父表。
Insert on conflict單行
支持場景如下。
支持沒有
on conflict
的表達式。支持含有
on conflict do nothing
的表達式。支持
on conflict do update
,必須更新所有insert的非PK(Primary Key,主鍵,以下簡稱PK)列,PK是否更新都可以,并且只能是col = excluded.col
方式更新。Hologres V1.3及以上版本支持更新部分非PK列,但是仍僅支持col = excluded.col
方式更新
使用示例如下。
BEGIN; CREATE TABLE test_insert_oneline ( pk1 int, pk2 int, col1 int, col2 int, PRIMARY KEY (pk1, pk2) ); COMMIT; --update所有非PK列,可以Fixed Plan INSERT INTO test_insert_oneline VALUES (1, 2, 3, 4) ON CONFLICT (pk1, pk2) DO UPDATE SET col1 = excluded.col1, col2 = excluded.col2; --update所有列(包含PK和非PK),可以Fixed Plan INSERT INTO test_insert_oneline VALUES (1, 2, 3, 4) ON CONFLICT (pk1, pk2) DO UPDATE SET col1 = excluded.col1, col2 = excluded.col2, pk1 = excluded.pk1, pk2 = excluded.pk2; --必須update所有非pk的要insert的列,此例子不包含col2,僅Hologres V1.3僅以上版本支持Fixed Plan INSERT INTO test_insert_oneline VALUES (1, 2, 3, 4) ON CONFLICT (pk1, pk2) DO UPDATE SET col1 = excluded.col1; --必須是set col = excluded.col方式更新,因此不能Fixed Plan INSERT INTO test_insert_oneline VALUES (1, 2, 3, 4) ON CONFLICT (pk1, pk2) DO UPDATE SET col1 = excluded.col1, col2 = 5;
Insert on conflict多行
insert on conflict多行時,表達式如下。
SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON; INSERT INTO TABLE (col1, col2, col3..) VALUES (?, ?, ?..), (?, ?, ?..) ON CONFLICT xxx;
需要配置GUC參數:
hg_experimental_enable_fixed_dispatcher_for_multi_values=on;
。Hologres從1.3.35開始,該參數默認為on
。不保證原子性,即一次性寫入多條的時候,如果沒報錯就是全部正常寫入了,如果報錯了有可能全部沒寫入也有可能部分寫入了部分沒寫入。
寫入多行另一種寫法表達式如下。
SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON; INSERT INTO TABLE selectunnest (ARRAY[TRUE, FALSE, TRUE]::bool[]), unnest(ARRAY[1, 2, 3]::int4[]), unnest(ARRAY[1.11, 2.222, 3]::float4[]) ON CONFLICT xxx;
需要配置GUC參數:
hg_experimental_enable_fixed_dispatcher_for_multi_values=on;
。寫入的列不能是數組類型。
unnest里ARRAY必須顯式轉換為對應列類型的數組類型。
使用示例如下。
BEGIN; CREATE TABLE test_insert_multiline ( pk1 int8, col1 float4, PRIMARY KEY (pk1) ); COMMIT; --支持Fixed Plan SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON; INSERT INTO test_insert_multiline SELECT unnest(ARRAY[1, 2, 3]::int8[]), unnest(ARRAY[1.11, 2.222, 3]::float4[]) ON CONFLICT DO NOTHING; --unnest里ARRAY沒有顯式cast,不支持Fixed Plan INSERT INTO test_insert_multiline SELECT unnest(ARRAY[1, 2, 3]), unnest(ARRAY[1.11, 2.222, 3]) ON CONFLICT DO NOTHING; --第一列是int8,所以應該cast為int8[],這里例子是int4[],因此不支持Fixed Plan INSERT INTO test_insert_multiline SELECT unnest(ARRAY[1, 2, 3]::int4[]), unnest(ARRAY[1.11, 2.222, 3]::float4[]) ON CONFLICT DO NOTHING;
局部更新場景
Hologres支持通過主鍵,對表的部分列更新,Fixed Plan同樣支持局部更新場景,需要滿足如下條件。
Insert的列需要與Update的列一一對應,包括數量和順序。
只能是
col = excluded.col
方式更新。
帶有條件判斷的Upsert
為了應對上游數據同PK行的亂序需求,支持類HBase CheckAndPut接口,Hologres支持帶有條件判斷的
Insert
或Update
語句走Fixed Plan,條件如下。插入單條數據時支持;插入多條數據時,需要設置GUC參數:
set hg_experimental_enable_fixed_dispatcher_for_multi_values=on;
。where
條件僅支持單個非PK字段且比較符需在=、<>、>、>=、<、<=、IS NULL、IS NOT NULL
范圍內 ,可對該非PK字段使用coalesce
函數。
使用示例如下。
BEGIN; CREATE TABLE test_check_and_insert ( pk int, col int, scn int, PRIMARY KEY (pk) ); COMMIT; --支持Fixed Plan --列已有值和常量比較 INSERT INTO test_check_and_insert AS old VALUES (1, 1, 1) ON CONFLICT (pk) DO UPDATE SET col = excluded.col, scn = excluded.scn WHERE old.scn > 0; --列已有值和寫入值比較 INSERT INTO test_check_and_insert AS old VALUES (1, 1, 1) ON CONFLICT (pk) DO UPDATE SET col = excluded.col, scn = excluded.scn WHERE old.scn > excluded.scn; --若已有值可能為null,可用coalesce INSERT INTO test_check_and_insert AS old VALUES (1, 1, 1) ON CONFLICT (pk) DO UPDATE SET col = excluded.col, scn = excluded.scn WHERE coalesce(old.scn, 3) > 2; INSERT INTO test_check_and_insert AS old VALUES (1, 1, 1) ON CONFLICT (pk) DO UPDATE SET col = excluded.col, scn = excluded.scn WHERE coalesce(old.scn, 3) > excluded.scn; --支持Fixed Plan SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON; --列已有值和常量比較 INSERT INTO test_check_and_insert AS old VALUES (1, 1, 1), (2, 3, 4) ON CONFLICT (pk) DO UPDATE SET col = excluded.col, scn = excluded.scn WHERE old.scn > 3; --也支持unnest寫法 INSERT INTO test_check_and_insert AS old SELECT unnest(ARRAY[5, 6, 7]::int[]), unnest(ARRAY[1, 1, 1]::int[]), unnest(ARRAY[1, 1, 1]::int[]) ON CONFLICT (pk) DO UPDATE SET col = excluded.col, scn = excluded.scn WHERE old.scn > 3;
Default列
表中含有Default列時,可以進行Fixed Plan的條件如下。
插入單條數據時支持;插入多條數據時,需要Hologres實例在V1.1.36及以上版本,若低于此版本請升級實例。同時需要設置GUC參數:
set hg_experimental_enable_fixed_dispatcher_for_multi_values=on;
。Hologres V1.3及以上版本支持有Default列的表
insert on conflict
表達式的Fixed Plan。之前版本實例有Default列的表,不支持insert on conflict
表達式的Fixed Plan。
使用示例如下。
BEGIN; CREATE TABLE test_insert_default ( pk1 int, col1 int DEFAULT 99, PRIMARY KEY (pk1) ); COMMIT; --支持Fixed Plan INSERT INTO test_insert_default (pk1) VALUES (1); --需要V1.1.36及以上版本支持 SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON; INSERT INTO test_insert_default (pk1) VALUES (1), (2), (3);
Serial列
表帶有自增序列Serial時,支持單條或者多條寫入進行Fixed Plan的條件如下。
需要配置GUC參數:
set hg_experimental_enable_fixed_dispatcher_autofill_series=on;
,從Hologres V1.3.25版本開始,該GUC參數默認為on
。插入多條數據時,還需配置GUC參數:
set hg_experimental_enable_fixed_dispatcher_for_multi_values=on;
。
使用示例如下。
BEGIN; CREATE TABLE test_insert_serial ( pk1 int, col1 serial, PRIMARY KEY (pk1) ); COMMIT; --支持Fixed Plan SET hg_experimental_enable_fixed_dispatcher_autofill_series = ON; INSERT INTO test_insert_serial (pk1) VALUES (1); --支持Fixed Plan SET hg_experimental_enable_fixed_dispatcher_autofill_series = ON; SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON; INSERT INTO test_insert_serial (pk1) VALUES (1), (2), (3);
UPDATE場景
Update表達式
Update時能進行Fixed Plan的表達式如下。
SET hg_experimental_enable_fixed_dispatcher_for_update = ON; UPDATE TABLE SET col1 = ?,col2 = ? WHERE pk1 = ? AND pk2 = ?;
Update場景使用
Update場景支持進行Fixed Plan的條件如下。
支持更新內部表,不支持更新外部表;支持更新分區子表,不支持更新分區父表;表必須有主鍵(PK)。
需要配置GUC參數:
hg_experimental_enable_fixed_dispatcher_for_update=on;
。Hologres從 V1.3.25版本開始,該參數廢棄使用,符合條件的Update
則會默認走Fixed Plan,但如果是Update更新多行時,需要配置GUC參數:set hg_experimental_enable_fixed_dispatcher_for_multi_values =on
。set
的列不能是主鍵(PK)。where條件里有且只能有全部的PK。
可以使用
pk in (?,?,?) 或 pk = ANY()
一次修改多條。示例:pk1 in (1,2) and pk2 = any('{3,4}') and pk3 = 5
,改(1,3,5),(1,4,5),(2,3,5),(2,4,5)
四條。where條件里同一列只能有一個條件(一模一樣的視為一個條件)。
使用示例如下。
BEGIN; CREATE TABLE test_update ( pk1 int, pk2 int, col1 int, col2 int, PRIMARY KEY (pk1, pk2) ); COMMIT; --支持Fixed Plan SET hg_experimental_enable_fixed_dispatcher_for_update = ON; UPDATE test_update SET col1 = 1, col2 = 2 WHERE pk1 = 3 AND pk2 = 4; --支持Fixed Plan SET hg_experimental_enable_fixed_dispatcher_for_update = ON; UPDATE test_update SET col1 = 1 WHERE pk1 = 3 AND pk2 = 4; --支持Fixed Plan SET hg_experimental_enable_fixed_dispatcher_for_update = ON; UPDATE test_update SET col1 = 1, col2 = 2 WHERE pk1 IN (1, 2) AND pk2 = ANY ('{3,4}'); --pk1多個過濾條件,不支持Fixed Plan UPDATE test_update SET col1 = 1, col2 = 2 WHERE pk1 = 3 AND pk1 = 4; --pk1多個過濾條件,不支持Fixed Plan UPDATE test_update SET col1 = 1, col2 = 2 WHERE pk1 IN (1, 2) AND pk1 = 1; --pk1多個過濾條件,但過濾條件相同,支持Fixed Plan SET hg_experimental_enable_fixed_dispatcher_for_update = ON; UPDATE test_update SET col1 = 1, col2 = 2 WHERE pk1 IN (1, 2) AND pk1 IN (1, 2) AND pk2 = 4;
DELETE場景
Delete表達式
Delete時能進行Fixed Plan的表達式如下。
SET hg_experimental_enable_fixed_dispatcher_for_delete = ON; DELETE FROM TABLE WHERE pk1 = ? AND pk2 = ? AND pk3 = ?;
Delete場景使用
Delete場景支持進行Fixed Plan的條件如下。
支持Delete內部表,不支持Delete外部表;支持Delete分區子表,不支持Delete分區父表;表必須有主鍵(PK)。
需要配置GUC參數:
hg_experimental_enable_fixed_dispatcher_for_delete=on;
。Hologres從 V1.3.25版本開始,該參數廢棄使用,符合條件的Delete
則會默認走Fixed Plan,但如果是Delete多行時,需要配置GUC參數:set hg_experimental_enable_fixed_dispatcher_for_multi_values =on
。where
條件里有且只能有全部的PK,從Hologres V1.3版本開始,支持where
過濾條件的最后一個字段為非PK字段,該非PK字段支持=、<>、>、>=、<、<=、IS NULL、IS NOT NULL
比較符以及使用coalesce
函數。可以使用
pk in (?,?,?) 或 pk = ANY()
一次刪除多條。示例:pk1 in (1,2) and pk2 = any('{3,4}') and pk3 = 5
,刪除(1,3,5),(1,4,5),(2,3,5),(2,4,5)
四條。同一列只能有一個條件(一模一樣的視為一個條件)。
使用示例如下。
BEGIN; CREATE TABLE test_delete ( pk1 int, pk2 int, col1 int, col2 int, PRIMARY KEY (pk1, pk2) ); COMMIT; --支持Fixed Plan,更多場景與Update樣例一致 SET hg_experimental_enable_fixed_dispatcher_for_delete = ON; DELETE FROM test_delete WHERE pk1 = 1 AND pk2 = 2;
SELECT場景
SELECT表達式
SELECT時能進行Fixed Plan的表達式如下。
SELECT col1, col2, col3, ... FROM TABLE WHERE pk1 = ? AND pk2 = ? AND pk3 = ?;
支持Select內部表,不支持外部表。
支持分區子表,不支持分區父表。
表必須有主鍵(PK)。
點查(key/value)場景
點查場景支持的情況如下。
where條件里有且只能有全部的PK。
可以使用
pk in (?,?,?) 或 pk = ANY()
一次查多條。示例:pk1 in (1,2) and pk2 = any('{3,4}') and pk3 = 5
,查(1,3,5),(1,4,5),(2,3,5),(2,4,5)
四條。同一列只能有一個條件(一模一樣的視為一個條件)。
如果有limit,limit的值必須
>0
。
使用示例如下。
BEGIN; CREATE TABLE test_select ( pk1 int, pk2 int, col1 int, col2 int, PRIMARY KEY (pk1, pk2) ); CALL set_table_property ('test_select', 'orientation', 'row'); COMMIT; --支持Fixed Plan SELECT * FROM test_select WHERE pk1 = 1 AND pk2 = 2;
PrefixScan場景
PrefixScan場景表達式
PrefixScan場景是指表有多個主鍵,查詢時按照左匹配原則只查幾列主鍵,查詢表達式如下。
SET hg_experimental_enable_fixed_dispatcher_for_scan = on; SELECT col1,col2,col3,... FROM TABLE WHERE pk1 = ? AND pk2 = ?; SELECT col1,col2,col3,... FROM TABLE WHERE pk1 = ? AND pk2 < ?;--從1.1.48版本開始支持pk最后一列條件為range SELECT col1,col2,col3,... FROM TABLE WHERE pk1 = ? AND pk2 BETWEEN ? AND ?;--從1.1.48版本開始支持pk最后一列條件為range
PrefixScan使用
PrefixScan的使用條件如下。
需要配置GUC參數:
hg_experimental_enable_fixed_dispatcher_for_scan=on;
,且實例在V1.3.35版本以上。表必須有Distribution Key,且
where
語句里必須包含所有的Distribution Key。where
語句里有且只有PK的Prefix。PrefixScan從V1.1.48版本開始支持主鍵最后一列條件設置為范圍(同時包含上限和下限)。說明Prefix定義: 若PK為
(pk1,pk2,pk3)
,則(pk1),(pk1,pk2)
為Prefix。僅行存表(包括行列共存)支持PrefixScan。
同一列只能有一個條件(一模一樣的視為一個條件)。
如果含有limit條件,limit的值必須大于0。
說明PrefixScan一次性返回所有結果行,如果結果的字節數大于
hg_experimental_fixed_scan_bytesize_limit
會報錯:scan result size larger than fixed scan size limit
,可以通過配置hg_experimental_fixed_scan_bytesize_limit
參數設置更符合場景的值,默認值為1048576,即1MB。示例如下,若表PK為
(pk1,pk2,pk3,pk4)
, Distribution Key為pk1,pk3
。BEGIN; CREATE TABLE test_select_prefix ( pk1 int, pk2 int, pk3 int, pk4 int, PRIMARY KEY (pk1, pk2, pk3, pk4) ); CALL set_table_property ('test_select_prefix', 'orientation', 'row'); CALL set_table_property ('test_select_prefix', 'distribution_key', 'pk1,pk3'); COMMIT; --沒有包含所有distribution key,不能走fixed plan SELECT * FROM test_select_prefix WHERE pk1 = ? AND pk2 = ?; --不是pk的prefix,不能走fixed plan SELECT * FROM test_select_prefix WHERE pk1 = ? AND pk3 = ?; --可以走fixed plan SET hg_experimental_enable_fixed_dispatcher_for_scan = ON; SELECT * FROM test_select_prefix WHERE pk1 = ? AND pk2 = ? AND pk3 = ?;
可以使用
pk in (?,?,?)
或pk = ANY()
一次性查多條,命令如下。pk1 IN (1,2) AND pk2 = 3 <=> scan(1,3),(2,3)兩組 pk2 =any('{3,4}') AND pk1 IN (1,2) <=> scan(1,3),(1,4),(2,3),(2,4)四組
使用示例
BEGIN; CREATE TABLE test_scan ( pk1 int, pk2 int, pk3 int, col1 int, PRIMARY KEY (pk1, pk2, pk3) ); CALL set_table_property ('test_scan', 'orientation', 'row'); CALL set_table_property ('test_scan', 'distribution_key', 'pk1,pk2'); COMMIT; INSERT INTO test_scan VALUES (1, 2, 3, 4); --支持Fixed Plan SET hg_experimental_enable_fixed_dispatcher_for_scan = ON; SELECT * FROM test_scan WHERE pk1 = 1 AND pk2 = 2; --支持Fixed Plan SET hg_experimental_enable_fixed_dispatcher_for_scan = ON; SELECT * FROM test_scan WHERE pk1 = 1 AND pk2 IN (2, 3); --支持Fixed Plan SET hg_experimental_enable_fixed_dispatcher_for_scan = ON; SELECT * FROM test_scan WHERE pk1 = ANY ('{3,4}') AND pk2 IN (2, 3); --支持fixed plan,pk最后一列是range條件,需要1.1.48及以上版本支持 SET hg_experimental_enable_fixed_dispatcher_for_scan = ON; SELECT * FROM test_scan WHERE pk1 = 1 AND pk2 = 1 AND pk3 > 1 AND pk3 < 4; --支持fixed plan,pk最后一列是range條件,需要1.1.48及以上版本支持 SET hg_experimental_enable_fixed_dispatcher_for_scan = ON; SELECT * FROM test_scan WHERE pk1 = 1 AND pk2 = 1 AND pk3 BETWEEN 1 AND 4; --不包含所有的distribution key,不支持Fixed Plan SELECT * FROM test_scan WHERE pk1 = 1; --不符合主鍵前綴Prefix,不支持Fixed Plan SELECT * FROM test_scan WHERE pk2 = 2;
COPY場景
Hologres從1.3.17版本開始,COPY
語句支持走Fixed Plan,與非Fixed Plan相比差異如下。
對比項 | Fixed Plan | 非Fixed Plan |
鎖類型 | 行鎖 | 表鎖 |
數據可見行 | 寫入即可見。 | Copy命令執行結束后可見。 |
性能 | 高 | 非常高 |
支持類型 | TEXT或BINARY | TEXT |
支持的主鍵沖突策略 | 支持如下策略:
| NONE(沖突則報錯) |
COPY
語句新增如下參數。
參數 | 說明 |
stream_mode | 是否走Fixed Plan,取值如下。
|
on_conflict | 沖突策略,取值如下:
|
命令示例如下。
COPY table_name (column0, column1, column2)
FROM
STDIN WITH (
format BINARY,
stream_mode TRUE,
on_conflict UPDATE);
非全列表現說明。
如果Copy寫入的列不是全列,則為局部更新,表現如下:
CREATE TABLE t0 ( id int NOT NULL, name text, age int, PRIMARY KEY (id) ); COPY t0 (id, name) FROM STDINWITH (stream_mode TRUE, on_conflict UPDATE); -- 上述COPY等價與如下 INSERT INTOINSERT INTO t0 (id, name) VALUES (?, ?) ON CONFLICT (id) DO UPDATE SETid = excluded.id, name = excluded.name;
如果Copy寫入的列不是全列,且未參與寫入的列設置了默認值屬性,表現如下:
CREATE TABLE t0 ( id int NOT NULL, name text, age int DEFAULT 0, PRIMARY KEY (id) ); COPY t0 (id, name) FROM STDINWITH (stream_mode TRUE, on_conflict UPDATE); -- 上述COPY等價與如下INSERT INTO -- 若id數據不存在,age列賦值default value; -- 若id數據已存在,age列不更新 INSERT INTO t0 (id, name, age) VALUES (?, ?, DEFAULT) ON CONFLICT (id) DO UPDATE SETid = excluded.id, name = excluded.name;
驗證Fixed Plan
通過FixedPlan執行的更新類SQL,在控制臺的實時導入RPS面板中會顯示為SDK類型,包括INSERT、UPDATE和DELETE類型的操作。建議實時寫入類Insert、Update、Delete都盡量優化為Fixed Plan方案,改善數據更新的效率。
通過查看SQL執行計劃(explain sql),如果返回的執行計劃中含有
FixedXXXNode
,即表示觸發了Fixed Plan,如下圖所示。如未生成含有FixedXXXNode
的執行計劃,請對照上文場景支持條件, 查看是否滿足條件。
性能調優
在某些場景上若是已經開啟Fixed Plan但還需要做性能調優時,可選擇如下方式。
Hologres V1.1.49版本開始針對Fixed Plan點查場景進行了優化,在大規模點查的情況下提升了30%以上吞吐。若有需要請升級實例至V1.1.49及以上版本。
客戶端合理的攢批(使用Holo Client會自動攢批),即一次執行SQL命令的數量,實踐證明數量為512或者512的倍數性能會更好。
常見問題
問題1:連接報錯:
role/database does not exist.
原因:用戶或DB不存在。
解決辦法:檢查連接信息,填寫正確的用戶名或DB名。
您可以登錄Hologres管理控制臺,單擊目標實例操作列中的管理,然后單擊數據庫管理,在用戶管理 和DB 授權頁面獲取并確認用戶名或DB名。
問題2:數據寫入過程中報錯:
the requested table name: xxx (id: xx, version: xx) mismatches the version of the table (id: xx, version: xx) from server.
原因:數據寫入過程中表元信息發生變化(如增加列)導致Table Version發生變化。
解決方案:重新建立連接,Fixed Plan會獲取新的表元信息并進行寫入。