資料庫查詢優化引擎可以怎樣實現查詢優化--邏輯查詢優化
本節大部分的資料來自《資料庫查詢優化的藝術》 23頁到第二章結束的內容
最常見的子查詢優化
IN 型別的優化
1.OUT_EXP (NOT) IN INNER_EXP_SELECT_SQL
2.OUT_EXP = ANY INNER_EXP_SELECT_SQL
第一種情況需要OUT_EXP與INNER_EXP都為非空的值,可以使用EXISTS來替代優化,OUT_EXP (NOT) EXISTS INNER_EXP_SELECT_SQL 達到優化的目的,同樣第二種情況只需要OUT_EXP不為空值 也可以使用EXISTS來實現優化處理。
很多時候在使用IN的時候其實是與 =ANY是等價的,比如
SELECT COL_1 FROM T1 WHERE COL_1 =ANY (SELECT COL_1 FROM T2);
SELECT COL_1 FROM T1 WHERE COL_1 IN (SELECT COL_1 FROM T2);
ALL/ANY/SOME 型別
OUT_EXP OPERATOR ALL/ANY/SOME (INNER_EXP_SQL);
ALL表示INNER_EXP所有的結果集都進行OPERATOR操作,ANY表示任意結果集進行OP操作,SOME表示一部分進行OP操作,而這裡的OP表示運算子,比如<>=,其中一下的語義是等價的
=ANY 與IN , SOME 與ANY , NOT IN 與 <>ALL , <>ANY表示與任何值都不相等 , VAL>ALL(INNER_EXP_SELSET ) 與 VAL > MAX (INNER_SELECT) VAL<ALL(INNER_SELECT) 與 VAL < MIN (INNER_SELECT) VAL>ANY(INNER_SELECT) 與 VAL > MIN(INNER_SELECT ) VAL<ANY(INNER_SELECT ) 與 VAL<MAX(INNER_SELECT ) VAL>=ALL(INNER_SELECT ) 與 VAL >= MAX (INNER_SELECT) VAL<= ALL(INNER_SELECT ) 與 VAL <= MIN(INNER_SELECT ) VAL>= ANY (INNER_SELECT ) 與 VAL>=MIN(INNER_SELECT ) VAL<= ANY (INNER_SELCT ) 與 VAL<=MAX(INNER_SELECT )
EXISTS型別
EXISTS是針對的結果集為boolean型別的返回值如果INNER_SELECT 存在OUT_SELECT 的所需要的值,name就會返回TRUE,否則為FALSE,很多時候IN的型別可以轉換為EXISTS的反半連結的優化
檢視重寫
檢視是基於表的物件,重寫檢視就是重寫表的引用物件。也就是作為子查詢的檢視sql進一步優化,*所有的檢視都可以使用子查詢替代,但是所有的子查詢都不完全能使用檢視替代。*重寫檢視也就是從原表中提取業務需要的欄位加以簡化查詢的結果,有興趣的讀者可以瞭解一下oracle的物化檢視重寫,以及複雜檢視合併,如果英文好的讀者可以嘗試從官網瞭解一下oracle的
LIKE規則
作為sql的一種支援模糊查詢的操作,如果使用不恰當會導致索引失效,所以使用替代謂詞的方案就十分的有必要,比如
name LIKE 'ABC%' 等價於 name >= 'ABC' AND name < 'ABC' ;
如果索引不是建立在name上的話,那就會產生fullScan的情況,所以要注意使用LIKE,如果能使用其他的替代方案就使用其他方案。
BETWEEN…AND 規則
作為sql的範圍過濾的操作,同樣也有可能導致索引失效而fullScan的出現,常用的替代方案是
userId BETWEEN 10 AND 20 等價於 userId >=10 AND userId <=20 ;
IN轉為OR 的規則
IN 的謂詞操作的在某些資料庫上都是fullScan這個都直接導致索引失效的情況,所以,通常使用EXISTS或者OR來替換,這裡的介紹OR的規則替換
age IN (7,8,9) 等價於 age =7 OR age =8 OR age =9 ;
IN轉為 ANY 規則
IN 轉OR 以及ANY的在生產上是經常使用到的,比如
age IN (7,8,9) 等價於 age ANY (7,8,9)
但是專案即將從oracle轉PG ,而PG 是不支援ANY操作的。
OR轉為 ANY 規則
這裡的OR轉ANY實則是多個OR的條件使用 ANY()來囊括在內,但是Mysql不支援。這裡不詳細舉例,有興趣讀者可以參考31頁有詳細描述。
ALL.ANY 轉為 集合函式規則
也就是上面提到的使用 MAX(),MIN()等聚合函式來實現優化,通常來說聚合函式的優化效率比ANY,ALL等要高很多。大概效率如下 MAX(),MIN() > ANY/ALL > EXISTS > IN
NOT 規則
NOT的規則其實就是取反的含義,通常重寫是因為操作的欄位如果建立了索引就使用><=等的替代方案來實現重寫提高效率。NOT (COL_1>COL2) 等價 COL_1<COL_2 前提是COL_1或者COL_2建立了索引
OR重寫為並集 規則
OR重寫為UNION 的規則一般都要建立在所操作的列是已經建立了索引,不然UNION也是會產生fullScan的操作出現。
條件簡化
如果sql指令碼不存在聚合函式的GROUPBY,可以使用HAVING裡面新增WHERE來簡化查詢結果。如果條件查詢中有大量的沒必要的(),可以通過等價的去掉括號實現優化。WHERE 後面不要新增表示式計算,表的連線演算法,一般都是使用規模小的放到外層來進行演算法關聯。這裡涉及到JOIN_LEFT ,JOIN_INNER,JOIN_RIGHT,等這些多表關聯的規則,優化都是通過,小表建立索引,然後索引體現在WHERE的條件裡面。
資料庫查詢優化藝術 這裡針對邏輯優化還有很精彩的介紹,但是筆者的歸納能力有限,暫時記錄這些生產上常用的,如果有興趣加深理解的可以自行參考書中的介紹,包括GROUPBY,ORDERBY的優化,連線消除,語義優化等內容。