應用迭代發版須執行如下動作
1、按目標需求全面壓力測試,優化潛在慢SQL或設置特殊優化參數(如:OPTIMIZER_OR_NBEXP)
2、達夢數據庫有數據導入,必須收集統計信息
達夢使用SF_INJECT_HINT系統函數對指定SQL增加HINT,保證SQL在不同環境的執行計劃相同,穩定執行效率。適合在SQL執行計劃較差或者走錯(比如走了索引但回表代價高于全表掃描、表連接錯誤等情況)且業務調整SQL語句代價比較大,需要立即優化見效的情況下使用。
一、SF_INJECT_HINT功能說明
SF_INJECT_HINT使用介紹
SF_INJECT_HINT系統函數的功能是對指定SQL增加HINT。可通過SYSINJECTHINT視圖查看已指定的SQL語句和對應的HINT;
SQL> select * from sys.SYSINJECTHINT;
使用方法如下:
SF_INJECT_HINT(SQL_TEXT,HINT_TEXT,NAME,DESCRIPTION,VALIDATA,FUZZY);
參數說明如下:
SQL_TEXT:要指定HINT的SQL語句或者片段;
HINT_TEXT:要為SQL指定的HINT;多個hint使用空格隔開;語法:參數名稱(參數值)
NAME:配置這條規則的名稱,通過這個名字,可以通過 sp_deinject_hint('名字'),進行規則取消
DESCRIPTION:對規則的詳細描述,可為NULL;
VALIDATA:規則是否生效,可為NULL,則為默認值TRUE;
FUZZY:SQL的匹配規則為精準匹配或模糊匹配。值為TRUE或NULL時,模糊匹配;值為FALSE或缺省時,精準匹配;
說明:FUZZY參數在老的版本中是不支持的(DM V8 1-1-190附近的版本才開始支持)
使用時的限制條件如下:
(1)INI參數ENABLE_INJECT_HINT需設置為1;
(2)SQL只能是語法正確的增刪改查語句;
(3)SQL會經過系統格式化,格式化之后的SQL和指定的規則名稱必須全局唯一;
(4)HINT一指定,則全局生效;
(5)系統檢查SQL匹配時,必須是整條語句完全匹配,不能是語句中子查詢匹配;
使用場景:
通過SF_INJECT_HINT函數為SQL指定HINT的方式,適合在SQL執行計劃較差或者走錯(比如走了索引但回表代價高于全表掃描、表連接錯誤等情況)且業務調整SQL語句代價比較大的情況下使用。
說明:
INJECT_HINT使用示例
(1)設置INI參數ENABLE_INJECT_HINT為1
ENABLE_INJECT_HINT參數表示是否啟用SQL指定HINT的功能,0:不啟用;1:啟用,默認0。動態,會話級參數,修改后無需重啟數據庫生效。
SQL> SP_SET_PARA_VALUE(1,'ENABLE_INJECT_HINT',1);
(2)會話級開啟MONITOR_SQL_EXEC,方便使用ET查看SQL執行計劃各個操作消耗的時間
sf_set_session_para_value('MONITOR_SQL_EXEC',1);
(3)首先查看測試SQL執行時間以及SQL執行計劃各個操作的耗時
執行sql:select * from tab1 where v1 like 'sdf%' or v2 like 'sdf%' limit 10
使用et(sql執行號)查看執行計劃中各個步驟的耗時情況
SQL> et(2748105249)
通過上面3步可發現執行計劃慢在哪一步,對于遇到sql包含OR條件,通過OPTIMIZER_OR_NBEXP可以優化OR表達式。在不變動參數的全局影響時,可以通過HINT方式,對個別SQL進行調整(這種HINT可以注入在后臺,不需要修改應用代碼,可以隨時取消)
參數名字:OPTIMIZER_OR_NBEXP
默認值:0
屬性:動態會話級
0:不優化;
1:生成 UNION_FOR_OR 操作符時,優化為無 KEY 比較方式;
2:OR 表達式優先考慮整體處理方式;
4:相關子查詢的 OR 表達也優考慮整體處理方式;
8:OR 布爾表達式的范圍合并優化;
16:同一列上同時存在常量范圍過濾和 IS NULL 過濾時的優化,如 C1 > 5 OR C1 IS NULL。
支持使用上述有效值的組合值,如 7 表示同時進行 1、2、4 的優化
在個別SQL中,我們可能調整為2,效果更好。
二、樣例測試說明
達夢版本:DM8.1.4.6
--1、構造數據
create table tab1(v1 varchar(30000),v2 varchar(30000),v3 varchar(30000));
create index idx_tab1_v1 on tab1(v1);
--2、待分析SQL
select * from tab1 where v1 like 'sdf%' or v2 like 'sdf%' limit 10
執行計劃如下
1 #NSET2: [1, 2, 156]
2 #PRJT2: [1, 2, 156]; exp_num(4), is_atom(FALSE)
3 #TOPN2: [1, 2, 156]; top_num(10)
4 #UNION FOR OR2: [1, 2, 156]; key_num(0), outer_join(-)
5 #BLKUP2: [1, 1, 156]; idx_tab1_v1(tab1)
6 #SSEK2: [1, 1, 156]; scan_type(ASC), idx_tab1_v1(tab1), scan_range['sdf','sdg'), is_global(0)
7 #SLCT2: [1, 1, 156]; (tab1.v2 >= 'sdf' AND tab1.v2 < 'sdg' AND exp11)
8 #CSCN2: [1, 1, 156]; INDEX33609591(tab1); btr_scan(1)
從如上執行計劃來看,這個sql的or條件被拆分了兩個sql,然后union結果集;
在保持全局參數為0的情況下,希望使用 OPTIMIZER_OR_NBEXP 為 2的效果,如何為這個語句修改參數?
手工對sql執行效率
select /*+OPTIMIZER_OR_NBEXP(2)*/ * from tab1 where v1 like 'sdf%' or v2 like 'sdf%' limit 10
1 #NSET2: [1, 1, 156]
2 #PRJT2: [1, 1, 156]; exp_num(4), is_atom(FALSE)
3 #TOPN2: [1, 1, 156]; top_num(10)
4 #SLCT2: [1, 1, 156]; ((tab1.v1 >= 'sdf' AND tab1.v1 < 'sdg') OR (tab1.v2 >= 'sdf' AND tab1.v2 < 'sdg'))
5 #CSCN2: [1, 1, 156]; INDEX33609591(tab1); btr_scan(1)
select /*+OPTIMIZER_OR_NBEXP(0)*/ * from tab1 where v1 like 'sdf%' or v2 like 'sdf%' limit 10
1 #NSET2: [1, 2, 156]
2 #PRJT2: [1, 2, 156]; exp_num(4), is_atom(FALSE)
3 #TOPN2: [1, 2, 156]; top_num(10)
4 #UNION FOR OR2: [1, 2, 156]; key_num(1), outer_join(-)
5 #BLKUP2: [1, 1, 156]; idx_tab1_v1(tab1)
6 #SSEK2: [1, 1, 156]; scan_type(ASC), idx_tab1_v1(tab1), scan_range['sdf','sdg'), is_global(0)
7 #SLCT2: [1, 1, 156]; (tab1.v2 >= 'sdf' AND tab1.v2 < 'sdg') SLCT_PUSHDOWN(TRUE)
8 #CSCN2: [1, 1, 156]; INDEX33609591(tab1) NEED_SLCT(TRUE); btr_scan(1)
--3、為特定SQLSQL語句修改參數 OPTIMIZER_OR_NBEXP 為 2
sf_inject_hint(
'* from tab1 where v1 like ''sdf%'' or v2 like ''sdf%'' limit',--sql語句或者片段
'OPTIMIZER_OR_NBEXP(2)',--參數調整說明,語法:參數名稱(參數值)
'inject_20250806',--這條調整規則的名字,通過這個名字,我們可以通過 sp_deinject_hint('名字'),進行規則取消
null,true,true
);
--4、查看計劃:確實修改成功了,or根據 OPTIMIZER_OR_NBEXP 為 2 的規則,作為一個整體處理了
1 #NSET2: [1, 1, 156]
2 #PRJT2: [1, 1, 156]; exp_num(4), is_atom(FALSE)
3 #TOPN2: [1, 1, 156]; top_num(10)
4 #SLCT2: [1, 1, 156]; ((tab1.v1 >= 'sdf' AND tab1.v1 < 'sdg') OR (tab1.v2 >= 'sdf' AND tab1.v2 < 'sdg'))
5 #CSCN2: [1, 1, 156]; INDEX33609591(tab1); btr_scan(1)
或查看系統視圖
SQL>select * from sys.SYSINJECTHINT;
- -5、規則取消
sf_deinject_hint('inject_20250806'); -- 進行規則取消
三、會影響SQL性能常用參數
除了上面說的參數(OPTIMIZER_OR_NBEXP)可以通過HINT優化外,還有如下兩個常用的參數會影響SQL性能
1、參數名字:COMPLEX_VIEW_MERGING
默認值:0
屬性:動態會話級
對于復雜視圖(一般含有GROUP或者集函數等)會執行合并操作,
使得 GROUP 分組操作在連接之后才執行。
0:不啟用;
1: 對不包含別名和同名列的視圖進行合并;
2: 視圖定義包含別名或同名列時也進行合并
在個別SQL中,我們可能調整為2,效果更好。
2、參數名字:FILTER_PUSH_DOWN
默認值:0
屬性:動態會話級
對單表條件是否下放的不同處理方式。
0: 表示條件不下放;
1: 表示在新優化器下, 對單表過濾條件進行下放處理;
2:表示在新優化器下對外連接、半連接進行下放條件優化處理;
4: 語義分析階段考慮單表過濾條件的選擇率, 超過0.5 則不下放,由后面進行代價計算選擇是否下放, 參數值 4 僅在參數取值包含 2 時有效,即將參數值設為 6 時有效;
8: 表示嘗試將包含非相關子查詢的布爾表達式進行下放。
支持使用上述有效值的組合值, 如 6 表示同時進行 2 和 4 的優化
在個別SQL中,我們可能調整為1,效果更好。
----end----