2013-04-03 18 views
0

我正在處理有關着陸頁的一些查詢。該頁面將爲用戶提供各種搜索選項。這些查詢將根據用戶選擇和啓動到DB2數據庫的各個部分構建。總而言之,有超過100個獨特的查詢。我正在努力降低性能,並且我有一個需要太長時間。基本結構是這樣的:SQL - 有問題的OR子句破壞查詢時間

SELECT ... 
FROM 
TABLE A 
--A few joins and a few left joins-- 
WHERE A.FIELD1 IS NOT NULL 
    AND A.FIELD2 IN (:parameter) --No more than two values in here 
    AND (
     A.FIELD3 IN ('ONE', 'TWO') 
    OR (A.FIELD3 IN ('THREE','FOUR') AND A.FIELD4 BETWEEN :x AND :y) 
) 
    AND A.FIELD5 IN (uncorrelated subquery, potentially returns over 1k values, usually less) 

FIELD2和3被選中,而其他只被過濾。 FIELD5用於連接,但這與使用子查詢進行篩選無關。問題來自(X OR Y)子句。查詢大約需要3秒鐘來執行。如果我刪除OR子句中的任一條件,它將在不到十分之一的時間內執行。奇怪的是,刪除它們都會使它回到3秒左右,這沒有多大意義,因爲它似乎並沒有增加太多數據集的大小。帶有OR子句的解釋計劃或沒有這兩個條件的解釋計劃幾乎完全相同,但它似乎並不是一個索引問題,因爲它看起來在相關表上找到了相同的索引。在這兩種情況下,最大的NLJOIN成本都很高。從OR子句中刪除一個條件(所以它只是一個AND),並且解釋計劃發生了顯着變化,雖然使用了相同的相關索引,但大大降低了成本並顯着改變了結構。

我試着解決這個問題與子查詢和工會,甚至使用兩個查詢之間的區別只有在該條款(這確實有助於這個實例一點點,但顯着減慢其他查詢),但沒有任何似乎有助於執行時間。由於查詢非常龐大,我無法真正發佈完整的詳細信息,但希望這足以讓這個想法貫穿始終。我知道OR子句有時可以將優化器放到一個循環中,所以我猜一般的建議是避免有問題的OR子句,或者將優化器推向更好的方向,這是非常值得讚賞的,即使它並不直接針對此示例。

回答

1

您可以嘗試使用case聲明。取而代之的

AND (A.FIELD3 IN ('ONE', 'TWO') 
OR (A.FIELD3 IN ('THREE','FOUR') AND A.FIELD4 BETWEEN :x AND :y)) 

使用

AND CASE WHEN A.FIELD3 IN ('ONE', 'TWO') THEN 1 
    WHEN A.FIELD3 IN ('THREE','FOUR') AND A.FIELD4 BETWEEN :x AND :y THEN 1 ELSE 0 END = 1 
+0

成功!這大大減少了幾次查詢的執行時間,同時使其它的查詢大部分時間不受影響。它可能略微增加了少數幾個人的執行時間,但它在單位數百分比內(並且沒有假設它在誤差範圍內),所以它絕對是一個整體收益。謝謝先生,你是個紳士和學者! – user1017413

0

它看似極端,但你可以聯合兩個快速版本一起......一個與該行

AND A.FIELD3 IN ('ONE', 'TWO') 

和一個與

A.FIELD3 IN ('THREE','FOUR') AND A.FIELD4 BETWEEN :x AND :y) 
+0

我用UNION ALL試了這個。它在這個特定的情況下確實有幫助,但是其他查詢的性能受到影響。不幸的是,結果導致業績淨下降。 – user1017413

0

嘗試:

SELECT ... 
FROM 
TABLE A 
--A few joins and a few left joins-- 
WHERE A.FIELD1 IS NOT NULL 
    AND A.FIELD2 IN (:parameter) 
    AND A.FIELD3 IN ('ONE', 'TWO', 'THREE', 'FOUR') 
    AND (A.FIELD3 IN ('ONE', 'TWO') OR A.FIELD4 BETWEEN :x AND :y) 
    AND A.FIELD5 IN (uncorrelated subquery) 
+0

這是一個很好的簡化(由於IN子句將包含列中的所有值,這使得第一個FIELD3過濾器無效),但不幸的是,它似乎沒有改變解釋計劃或執行時間。 – user1017413