什麼是QueryMapping
KingbaseES Query Mapping 是一種查詢映射功能。有過SQL優化經歷的人都知道,對於有些SQL性能問題,可能需要涉及到SQL層面的修改,這不僅麻煩,而且在已上線的系統還存在很大的風險。KingbaseES V8R6 提供了query mapping功能,用户可以通過SQL映射,可以避免直接修改SQL的過程。
QueryMapping的作用
一個無法使用索引的查詢語句,通過QueryMapping,可以解決性能問題。
假設應用有這麼一條SQL : select id from v_t1 where upper(name)=$1; 可以看下執行計劃:由於做了upper轉換,無法使用索引。
kingbase=# explain analyze select id from t1 where upper(name)='A1234567';
QUERY PLAN
------------------------------------------------------------------------------------------------------
Seq Scan on t1 (cost=0.00..20435.00 rows=5000 width=4) (actual time=44.860..190.009 rows=1 loops=1)
Filter: (upper(name) = 'A1234567'::text)
Rows Removed by Filter: 999999
Planning Time: 0.113 ms
Execution Time: 190.025 ms
(5 行記錄)
KingbaseES Query Mapping 實現不修改SQL,並且能快速解決問題。
set enable_query_rule = on
--創建SQL映射關係
select create_query_rule('qm1','select id from t1 where upper(name)=$1;','select id from t1 where name=lower($1);', true, 'text');
explain (usingquerymapping,analyze) select id from t1 where upper(name)='A1234567';
QUERY PLAN
----------------------------------------------------------------------------------------------------------------
Index Scan using ind_t1_name on t1 (cost=0.42..8.44 rows=1 width=4) (actual time=0.024..0.025 rows=1 loops=1)
Index Cond: (name = 'a1234567'::text)
Planning Time: 0.089 ms
Execution Time: 0.040 ms
(4 行記錄)
延伸思考
KingbaseES Query Mapping用一個性能良好的SQL語句,替換原SQL語句,實現性能的提升。如果SQL語句的執行性能良好,但解析性能較慢,是否可以解決SQL語句僅能在事務中實現軟解析。
實驗場景
一個複雜查詢
一個語句複雜的視圖,雖然執行性能優良,但解析需要較長的時間,造成查詢語句的整體運行時間較長。
kingbase=# explain analyze select id from sch01.v_tun1k where id = 8888;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------
Append (cost=0.28..8293.50 rows=1000 width=4) (actual time=0.088..4.602 rows=1 loops=1)
...
Planning Time: 376.659 ms
Execution Time: 6.621 ms
每次查詢返回結果的時間,如下。
kingbase=# select id from sch01.v_tun1k where id = 888; \watch
id
-----
888
(1 行記錄)
時間:374.361 ms
2022年09月25日 星期日 15時23分37秒 (每 2s)
id
-----
888
(1 行記錄)
時間:377.814 ms
2022年09月25日 星期日 15時23分39秒 (每 2s)
id
-----
888
(1 行記錄)
時間:381.633 ms
2022年09月25日 星期日 15時23分41秒 (每 2s)
id
-----
888
(1 行記錄)
時間:382.636 ms
2022年09月25日 星期日 15時23分44秒 (每 2s)
id
-----
888
(1 行記錄)
時間:378.316 ms
函數實現軟解析
使用函數可以在同一會話中,執行6次後,實現軟解析。
create or replace function f_tun1k(int)
returns table(id int)
language plsql
as
$$
begin
return query select id from sch01.v_tun1k where id = $1;
end;
$$
;
kingbase=# select *,round(date_part('sec',clock_timestamp()-now())*1000,3)||'ms' ms from f_tun1k(8888) ;\watch
id | ms
------+-----------
8888 | 456.109ms
(1 行記錄)
2022年09月25日 星期日 15時12分00秒 (每 2s)
id | ms
------+-----------
8888 | 382.978ms
(1 行記錄)
2022年09月25日 星期日 15時12分02秒 (每 2s)
id | ms
------+-----------
8888 | 391.402ms
(1 行記錄)
2022年09月25日 星期日 15時12分05秒 (每 2s)
id | ms
------+-----------
8888 | 380.328ms
(1 行記錄)
2022年09月25日 星期日 15時12分07秒 (每 2s)
id | ms
------+-----------
8888 | 385.995ms
(1 行記錄)
2022年09月25日 星期日 15時12分09秒 (每 2s)
id | ms
------+-----------
8888 | 382.862ms
(1 行記錄)
2022年09月25日 星期日 15時12分12秒 (每 2s)
id | ms
------+---------
8888 | 9.208ms
(1 行記錄)
2022年09月25日 星期日 15時12分14秒 (每 2s)
id | ms
------+---------
8888 | 7.971ms
(1 行記錄)
2022年09月25日 星期日 15時12分16秒 (每 2s)
id | ms
------+---------
8888 | 8.243ms
(1 行記錄)
將函數與QueryMapping結合
創建SQL映射關係
kingbase=# select create_query_rule('qm10', 'select id from sch01.v_tun1k where id = $1;', 'select id from f_tun1k($1) ;', true, 'text');
create_query_rule
-------------------
(1 行記錄)
函數與QueryMapping結合的效果,在同一會話中,原SQL實現了軟解析。
kingbase=# select id from sch01.v_tun1k where id = 888; \watch
id
-----
888
(1 行記錄)
時間:10.250 ms
2022年09月25日 星期日 15時21分34秒 (每 2s)
id
-----
888
(1 行記錄)
時間:7.958 ms
2022年09月25日 星期日 15時21分36秒 (每 2s)
id
-----
888
(1 行記錄)
時間:9.958 ms
2022年09月25日 星期日 15時21分38秒 (每 2s)
id
-----
888
(1 行記錄)
時間:10.581 ms
2022年09月25日 星期日 15時21分40秒 (每 2s)
id
-----
888
(1 行記錄)
時間:11.401 ms
在語句塊中實現軟解析
創建SQL映射關係,在語句塊中實現QueryMapping,需要semantics鍵值。
kingbase=# select create_query_rule('qm11', 'select id from sch01.v_tun1k where id = $1;', 'select id from f_tun1k($1) ;', true, 'semantics');
create_query_rule
-------------------
(1 行記錄)
在一個會話中,語句塊使用組合的軟解析效果。
kingbase=# do
kingbase-# $$
kingbase$# declare
kingbase$# v_id int ;
kingbase$# v_ref int;
kingbase$# begin
kingbase$# v_id := (random() * 1000000)::int;
kingbase$# select id into v_ref from sch01.v_tun1k where id = v_id;
kingbase$# raise notice ' ID = % , % ',v_ref , round(date_part('sec', clock_timestamp() - now()) * 1000,3) || 'ms';
kingbase$# end;
kingbase$# $$ \watch
注意: ID = 387169 , 8.635ms
2022年09月25日 星期日 15時33分01秒 (每 2s)
ANONYMOUS BLOCK
注意: ID = 35458 , 10.489ms
2022年09月25日 星期日 15時33分03秒 (每 2s)
ANONYMOUS BLOCK
注意: ID = 39627 , 9.775ms
2022年09月25日 星期日 15時33分05秒 (每 2s)
ANONYMOUS BLOCK
注意: ID = 730817 , 10.634ms
2022年09月25日 星期日 15時33分07秒 (每 2s)
ANONYMOUS BLOCK
注意: ID = 582763 , 9.363ms
2022年09月25日 星期日 15時33分09秒 (每 2s)
ANONYMOUS BLOCK
注意: ID = 148173 , 9.186ms
2022年09月25日 星期日 15時33分11秒 (每 2s)
ANONYMOUS BLOCK
注意: ID = 800521 , 9.766ms
2022年09月25日 星期日 15時33分13秒 (每 2s)
ANONYMOUS BLOCK
總結
目前,QueryMapping功能需要手動創建查詢腳本的對照關係,不便於大規模的應用,對於頻繁且無法優化的查詢,也可以提升執行性能。
KINGBASE研究院