1.基本規(guī)則
盡量早下推
選擇合適的連接
子查詢轉(zhuǎn)連接
參考:
https://docs.vastdata.com,cn/zh CN/VastbaseG100/V2.2.15/1/3e9f8b619dd94363b34fd5b58b14d2ab
1.1 相關(guān)概念
子查詢與子鏈接
沿用了pg的概念,在from后面叫子查詢,在其他關(guān)鍵字后面都叫子鏈接;其他系數(shù)據(jù)庫產(chǎn)品沒有區(qū)分這種概念。
子鏈接存在于什么地方?
- select后面(目標列,target list)
- where后面
- having后面
我們能調(diào)的大致就如上三個方面。在from后面的子查詢?nèi)斯じ深A(yù)的較少,vb產(chǎn)品本身已經(jīng)做了較多優(yōu)化。
sublink可以分為以下幾類:
- exist sublink:對應(yīng)EXIST、NOT EXIST語句。
- any_sublink:對應(yīng)op ANY(select..)語句,其中OP可以是“<”、“>”、“="操作符,IN/NOT IN (select..)也屬于這一類。
- all sublink:對應(yīng)op ALL(select..)語句,其中OP可以是“<”、“>”、“=”操作符。
- rowcompare sublink:對應(yīng)record op(select ..)語句,行比較。
- expr_sublink:對應(yīng)(SELECT with single targetlist item ...)語句,僅僅選擇一列。
- array sublink:對應(yīng)ARRAY(select...)語句。
- cte sublink:對應(yīng)with query(...)語句。
相關(guān)子鏈接、非相關(guān)子鏈接:
- select * from t1 where t1.i1=(select t2.i1 from t2 where t2.i2 = 1 limit 1);
- select* from t1 where t1.i1 = (select t2.i1 from t2 where t2.i2 = t1.i2 limit 1);
In-sublink(非相關(guān)子鏈接,非易變函數(shù))例子:

Exist-sublink包含相關(guān)條件: where子句中必須包含上一層查詢的表中的列,子查詢的其它部分不能含有上層查詢表中的列。
其它限制如下:
子查詢必須含有from子句。
子查詢不能含有with子句。
子查詢不能含有聚集函數(shù)。
子查詢里不能包含集合操作、排序、limit、windowagg、having操作。
子查詢不能包含易變函數(shù)。
例:

2.常用的調(diào)優(yōu)規(guī)則
2.1 lazyagg
(惰性聚合)
核心思想:
通過推遲某些聚合操作的執(zhí)行,直到進行了過濾或連接等操作之后,以此來減少計算量和提高查詢性能
場景:
基表數(shù)據(jù)量大、distinct值較多
子查詢有g(shù)roupby,關(guān)聯(lián)外表后還有g(shù)roup by
關(guān)聯(lián)字段是內(nèi)層的group by字段(或之一)
參考:
https://blog.csdn.net/devcloud/article/details/125457358
例:

2.2 magicset
核心思想:
將主查詢中的where過濾條件下推到子查詢中,實際中是把表下推,多一次關(guān)聯(lián)。
先針對子查詢的關(guān)聯(lián)字段進行關(guān)聯(lián),分組聚集,再和主查詢進行關(guān)聯(lián),減少相關(guān)子鏈接的重復(fù)掃描,提升查詢效率。
場景:
子查詢/子鏈接(=,>,<)
關(guān)聯(lián)聚合子查詢,子查詢數(shù)據(jù)量很大,條件下推大大減少數(shù)據(jù)量。
過濾條件是來自于聚合子查詢與外表連接的那個表
默認的rewrite_rule就是magicset
postgres=# show rewrite_rule ;
rewrite_rule
--------------
magicset
(1 row)
參考:
https://blog.csdn.net/robinson1988/article/details/139048758
例:


2.3 intargetlist
核心思想:提升targetlist中的子查詢
場景:子查詢在目標列中,有聚集函數(shù)
例:

例:

2.4 uniquecheck
核心思想:提升無agg的子鏈接語句,在執(zhí)行時檢查返回行數(shù)是否為1行。
場景:無agg的相關(guān)子鏈接(非相關(guān)子查詢不適用),每個子鏈接只有一行輸出(Unique check required)
例:

2.5 intargetlist, uniquecheck
場景:
targetlist中的無agg的子查詢
例:

2.6 enable_sublink_pullup_enhanced
核心思想:
使用增強后的sublink查詢重寫規(guī)則,包括where、having 子句的子鏈接
提升場景:where,having子句中,子查詢含聚集函數(shù)
例:

例:

2.7 qrw_inlist2join_optmode
核心思想:
控制使用inlist-to-join對SQL進行改寫
例·:
set qrw_inlist2join_optmode='rule base'
SELECT* FROM rewrite_rule_hint_t5 WHERE slot = '5' AND (name) lN
(SELECT name FROM rewrite_rule_hint_t5 WHERE sIot='5' AND cid IN (5,100,1001,1002,103,1004,1005,1006,1007,2000,4000,10781986,10880002) LIMIT 50);


其中rule base是強制轉(zhuǎn)連接,此外還有另外兩種選項:cost base、超閾值轉(zhuǎn)連接
2.8 disable_pullup_expr_sublink
核心思想:禁止表達式的子鏈接提升
例:

2.9 no_expand
核心思想:不提升子查詢
場景:
選擇率較低且可以使用索引過濾訪問頁面的子查詢,嵌套執(zhí)行不會導(dǎo)致性能下降過多,而提升之后擴大了查詢路徑的搜索范圍,可能導(dǎo)致性能變差。
例:

實際使用中no_expand因包含disable_pullup_expr_sublink的功能,所以使用的情況比disable_pullup_expr_sublink要多。
2.10 predpush、predpushnormal、predpushforce
核心思想:
predpush可以將謂詞下推到子查詢塊中
場景:
在父查詢塊中的數(shù)據(jù)量較小或子查詢(group by/distinct)中可以利用索引的場景下能夠提升性能,連接條件下推。
predpush的rewrite_rule規(guī)則有3個,分別是:
- predpushnormal:嘗試下推謂詞到子查詢中。(常用,能下去就下去)
- predpushforce:嘗試下推謂詞到子查詢中,盡量利用索引掃描
- predpush:利用代價在predpushnormal和predpushforce中選擇一個最優(yōu)的分布式計劃,但是會增加優(yōu)化時間。
此外還有
predpush_same_level:同層下推,前提:set rewrite rule='predpushforce';


2.11 from_collapse_limit, join_collapse_limit
核心思想:根據(jù)生成的FROM列表的項數(shù)來判斷優(yōu)化器是否將把子查詢合并到上層查詢,如果FROM列表項個數(shù)小于等于該參數(shù)值,優(yōu)化器會將子查詢合并到上層查詢。
原理:
根據(jù)得出的列表項數(shù)來判斷優(yōu)化器是否執(zhí)行把除FULL JOINS之外的JOIN構(gòu)造重寫到FROM列表中。
SELECT * FROM table1 t1 JOlN table2 t2 ON t1.id =t2.id
JOIN (SELECT * FROM table3 t3 jOlN table4 t4 ON t3.id = t4.id) sub ON t2.id = sub.id;
- 解析FROM列表FROM列表包含三個部分:
table1 t1 table2 t2 子?xùn)嗽?(SELECT* FROM table3 t3 JOlN table4 t4 ON t3.id = t4.id) sub - 遞歸處理每個FROM列表項優(yōu)化器會遞歸地處理每個FROM列表項:
對于table1 t1和table2 t2,它們是簡單的表引用,直接添加到JOIN 列表中。
對于子?xùn)嗽僺ub,優(yōu)化器會進一步遞歸處理其內(nèi)部的FROM 列表(table3 t3 和 table4 t4) - 合并子問題的結(jié)果如果子查詢的結(jié)果(sub)的長度不超過fromcollapselimit,則將其合并到當前的JOIN 列表中。
否則,將子查詢的結(jié)果作為一個整體添加到當前的JOIN 列表中。
假設(shè)from collapse limit=8,則最終生成的JOIN 列表為:[table1 t1,table2 t2,table3 t3, table4 t4]
如果from collapse limit =3,則子查詢的結(jié)果不會被合并,最終生成的JOIN列表為:[table1t1,table2 t2,(table3 t3 JOIN table4 t4) sub]
場景:
表連接的數(shù)據(jù)比較多,超過8個。
2.12 try_vector_engine_strategy
核心思想:
使用向量化引擎
向量化執(zhí)行引擎具有以下優(yōu)點:
- 一次一個batch,讀取更多數(shù)據(jù),節(jié)省10。
- batch中記錄較多,CPU cache命中率提升。
- Pipeline模式執(zhí)行,所數(shù)調(diào)用次數(shù)少。
- 一次處理一批數(shù)據(jù),效率高。
場景:
分析類復(fù)雜查詢:如果查詢語句中包含表達式計算、多表join、聚集等操作時,通過轉(zhuǎn)換為向量化執(zhí)行能夠獲得性能提升。

2.13 rownumenhance/enable_constraint_optimization
可以將rownum<const或rownum<=const 的場景轉(zhuǎn)為 limit 常量算子
消減不必要的條件
例:

2.14 總結(jié)

3.各版本新增規(guī)則
3.1 【2.2.15版本】新增
2.2.15.3
enable_any_sublink_pullup_enhanced, 啟用此選項后計劃器會嘗試將相關(guān)子連接進行提升,生成更好的執(zhí)行計劃。(即提升any)2.2.15.4
rewrite_rule='predpushnormal',query dop=1支持謂詞推入。2.2.15.7
enable remove unused outputs
功能描述:用于減少子查詢中不必要的目標列投影。對子查詢的目標列進行優(yōu)化,如果沒有被上層引用,滿足條件的情況下可以不進行投影,以提升效率。
3.2 【3.0.8版本】新增
- enablejeenhanced:
在查詢語句中,支持對左外連接進行優(yōu)化,消除不需要的右表,提升查詢效率
- enablejeenhanced:
SELECT DISTINCT test1_1200501.* FROM test1_1200501 LEFT JOlN test2_1200501 ON test1_1200501.id=test2_1200501.id;
- rewrite rule增加self_join_elimination,magicset
自連接消除是指對多次引用同一表的連接查詢,進行對重復(fù)掃描的消除優(yōu)化
- rewrite rule增加self_join_elimination,magicset
SELECT a.id, b.*FROM table_1238182 a JOlN table_1238182 b ON a.id=b.id;
- rewrite rule增加fkey join elimination
當一個表(子表)通過外鍵引用另一個表(主表)的主鍵時,如果子表中的每一行都與主表中的唯一一行相匹配,那么這種一對一的主外鍵連接將被優(yōu)化器消除。
- rewrite rule增加fkey join elimination
- rewrite_rule增加order_by_elimination:
消除多余ORDER BY。支持場景如下:
查詢中帶有連接操作(LEFT JOIN、INNER JOIN等),同時不含有rownum表達式,可以消除連接兩個子查詢中頂層
的 ORDER BY 子句。
查詢中存在集合操作(UNION ALL等),同時不包含rownum表達式,可以消除集合兩邊中頂層的ORDER BY子句。
ORDERBY所在該層查詢中,不存在LIMIT子句,不存在DISTINCT ON子句。
外層查詢目標列中存在聚集函數(shù),內(nèi)層查詢中的ORDER BY可以進行消除。
如存在多層嵌套,更深層的子查詢中的ORDER BY也可以進行消除。
子連接中(IN/EXISTS)的ORDER BY可以進行消除。
- rewrite_rule增加order_by_elimination:
4.規(guī)則限制
4.1 限制1

4.2 限制2

參考
