手動(dòng)調(diào)整Join順序
本文介紹如何通過Hint實(shí)現(xiàn)手動(dòng)調(diào)整Join順序。
功能介紹
AnalyticDB MySQL版支持復(fù)雜的聯(lián)表(Join)查詢且默認(rèn)提供了自動(dòng)調(diào)整Join順序的功能。但查詢語句和表的過濾條件隨時(shí)可能發(fā)生變化,而且如果數(shù)據(jù)特征復(fù)雜,自動(dòng)調(diào)整Join順序功能不一定在所有場景下都能很好地預(yù)估查詢特征,并選擇出最優(yōu)的Join順序。而不優(yōu)的Join順序可能造成中間結(jié)果集膨脹中間結(jié)果集數(shù)據(jù)量較大、內(nèi)存消耗大等問題,進(jìn)而影響查詢性能。
為解決上述問題,AnalyticDB MySQL版支持通過Hint/*+ reorder_joins*/
來開啟或關(guān)閉調(diào)整Join順序功能,其中:
/*+ reorder_joins=true*/
:開啟自動(dòng)調(diào)整Join順序功能。開啟后,系統(tǒng)會(huì)自動(dòng)調(diào)整Join順序。AnalyticDB MySQL版默認(rèn)開啟調(diào)整Join順序功能,因此在執(zhí)行SQL查詢時(shí)無需使用該Hint也會(huì)自動(dòng)調(diào)整Join順序。/*+ reorder_joins=false*/
:關(guān)閉自動(dòng)調(diào)整Join順序功能。關(guān)閉后,您可以根據(jù)查詢的數(shù)據(jù)特征手動(dòng)調(diào)整Join順序,讓查詢直接根據(jù)SQL書寫方式中的Join順序來執(zhí)行。
/*+ reorder_joins*/
為會(huì)話級(jí)別的Hint,僅對(duì)目標(biāo)SQL查詢語句生效。
調(diào)整方法
調(diào)整前
查詢語句
原始的Query10語句如下:
說明本文以TPC-H中的Query10為例介紹手動(dòng)調(diào)整Join順序的方法及查詢效果。更多關(guān)于TPC-H的詳細(xì)說明,請(qǐng)參見TPC-H。
由于AnalyticDB MySQL版的自動(dòng)調(diào)整Join順序功能默認(rèn)開啟,在執(zhí)行如下查詢語句時(shí)使用了Hint
/*+ reorder_joins=false*/
來模擬Join順序不優(yōu)的場景。
SELECT c_custkey, c_name, Sum(l_extendedprice * (1 - l_discount)) AS revenue, c_acctbal, n_name, c_address, c_phone, c_comment FROM customer c, orders o, lineitem l, nation n WHERE c_custkey = o_custkey AND l_orderkey = o_orderkey AND o_orderdate >= date '1993-10-01' AND o_orderdate < date '1993-10-01' + INTERVAL '3' month AND l_returnflag = 'R' AND c_nationkey = n_nationkey GROUP BY c_custkey, c_name, c_acctbal, c_phone, n_name, c_address, c_comment ORDER BY revenue DESC LIMIT 20;
Join順序
如果按照如上SQL的書寫方式,Join的順序應(yīng)該是:
customer JOIN orders JOIN lineitem JOIN nation;
查詢結(jié)果
此時(shí),執(zhí)行計(jì)劃中各個(gè)JOIN的臨時(shí)結(jié)果如下:
說明查看執(zhí)行計(jì)劃的步驟,請(qǐng)參見使用執(zhí)行計(jì)劃分析查詢。
表
customer
Join表orders
,輸出57069行數(shù)據(jù)至臨時(shí)結(jié)果集tmp1
。臨時(shí)結(jié)果集
tmp1
Join表lineitem
,輸出114705行數(shù)據(jù)至另一個(gè)臨時(shí)結(jié)果集tmp2
。臨時(shí)結(jié)果集
tmp2
Join表nation
,輸出114705行數(shù)據(jù)作為最終結(jié)果。
3次Join累積輸出結(jié)果行數(shù)為:57069 + 114705 + 114705 = 286479。
調(diào)整后
查詢語句
在SQL語句中添加
/*+ reorder_joins=false*/
的Hint來關(guān)閉AnalyticDB MySQL版的自動(dòng)調(diào)整Join順序功能,并手動(dòng)調(diào)整Join的順序,調(diào)整順序后的SQL語句如下:/*reorder_joins=false*/ SELECT c_custkey, c_name, Sum(l_extendedprice * (1 - l_discount)) AS revenue, c_acctbal, n_name, c_address, c_phone, c_comment FROM customer c, orders o, nation n, lineitem l WHERE c_custkey = o_custkey AND c_nationkey = n_nationkey AND l_orderkey = o_orderkey AND o_orderdate >= date '1993-10-01' AND o_orderdate < date '1993-10-01' + INTERVAL '3' month AND l_returnflag = 'R' GROUP BY c_custkey, c_name, c_acctbal, c_phone, n_name, c_address, c_comment ORDER BY revenue DESC LIMIT 20;
Join順序
如果按照如上SQL的書寫方式,Join的順序應(yīng)該是:
customer JOIN orders JOIN nation JOIN lineitem
查詢結(jié)果
此時(shí),執(zhí)行計(jì)劃中各個(gè)JOIN的臨時(shí)結(jié)果如下:
說明查看執(zhí)行計(jì)劃的步驟,請(qǐng)參見使用執(zhí)行計(jì)劃分析查詢。
表
customer
Join表orders
,輸出57069行數(shù)據(jù)至臨時(shí)結(jié)果集tmp1
。臨時(shí)結(jié)果集
tmp1
Join表nation
,輸出57069行數(shù)據(jù)至臨時(shí)結(jié)果集tmp2
。臨時(shí)結(jié)果集
tmp2
Join表lineitem
,輸出114705行數(shù)據(jù)作為最終結(jié)果。
3次Join累積輸出結(jié)果行數(shù)為:57069 + 57069 + 114705 = 228843。
相較于Join順序調(diào)整前(輸出286479行數(shù)據(jù)),減少了20%的輸出行數(shù)。從上述對(duì)比結(jié)果中可以看出,不同的Join順序會(huì)影響中間臨時(shí)結(jié)果集的大小,因此若發(fā)現(xiàn)AnalyticDB MySQL版的Join順序不優(yōu),您可以手動(dòng)調(diào)整Join順序來提升SQL查詢性能。