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。
DataWorksData Integration即時寫入資料至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會擷取新的表元資訊並進行寫入。