2014-03-19 59 views
2
INSERT INTO table3 
SELECT 
    tbl1.pk_1, tbl1.pk_2, tbl2.pk_3, tbl1.pk4 
FROM 
    table1 tbl1, table2 tbl2 
WHERE 
    tbl1.pk_1 = 'root' and 
    NOT EXISTS 
    (SELECT 1 FROM table3 tbl3 
    WHERE tbl3.pk_1 = tbl1.pk_1 and tbl3.pk_2 = tbl1.pk_2 and tbl3.pk_3 = tbl2.pk_3 and tbl3.pk_4 = tbl1.pk_4) 
; 

我的SQL語句看起來是這樣的。 table1和table3有超過1000000行,table2有100行。這個SQL語句非常慢。完成需要超過100秒。有什麼辦法可以改善它嗎?如何提高NOT EXISTS在Oracle的性能

+1

更好的去MERGE語句。 – San

+0

你能在所有三張表上顯示你有什麼索引和限制嗎? –

+2

還有,就是tbl1'和'tbl2'故意'之間的交叉聯接?我覺得有一個缺少連接謂詞... –

回答

0

我敢肯定,你的表表達式是不完整的:

FROM 
    table1 tbl1, table2 tbl2 

你(可能是意外)生產Table 1和Table之間的笛卡爾積,與百萬×100記錄在內存中。你的表表達式可能應該閱讀:

FROM 
    table1 tbl1, table2 tbl2 
WHERE 
    tbl1.some_column = tbl2.some_column 

甚至更​​好(以防止今後發生這種事)

FROM 
    table1 tbl1 
JOIN 
    table2 tbl2 ON tbl1.some_column = tbl2.some_column 
+0

table1和table2是獨立的。我們的應用程序需要在table1和table2之間執行笛卡爾積。我認爲這個瓶頸是「不存在」,它需要一個「NESTED LOOPS ANTI」搜索。我想知道有沒有更好的「不存在」。 – eeandrew

+0

好的,我明白了。那麼你預計每次更新有多少記錄?即「NOT EXISTS」謂詞是否會再次刪除從笛卡爾積生成的大部分元組? –

+0

是的。雖然笛卡爾積幾百萬行,但只有幾行(大約100)會通過「不存在」條件。 – eeandrew

1

使用合併,它提供更快

merge into table3 tbl3 
using (select tbl1.pk_1, tbl1.pk_2, tbl2.pk_3, tbl1.pk4 
     from table1 tbl1, table2 tbl2 
     where tbl1.pk_1 = 'root') tb1 
    on (tbl3.pk_1 = tbl.pk_1 and tbl3.pk_2 = tbl.pk_2 and tbl3.pk_3 = tbl.pk_3 and tbl.pk_4 = tbl1.pk_4) 
when not matched then 
    insert (tbl3.pk_1, tbl3.pk_2, tbl3.pk_3, tbl3.pk_4) 
    VALUES (tbl.pk_1, tbl.pk_2, tbl.pk_3, tbl.pk_4); 
+0

我測試了MERGE.On我的服務器,實際上它慢了兩倍。 – eeandrew

+0

table3上有索引嗎?如果沒有,請在(pk_1,pk_2,pk_3,pk_4)上創建複合索引後嘗試。 – San

+0

是的,pk_1,pk_2,pk_3,pk_4是複合索引 – eeandrew

1

我發現它是很難提高此SQL語句的性能。我測試MERGE,但它需要超過200秒。即使性能可以提高,我想它只能改善1秒或2秒,這不符合我們的業務要求。 (我有大約20個像這樣的SQL語句)。 所以我回顧了我們的業務邏輯,我發現這個SQL語句是沒有必要的。我們只需要一個更仔細的算法來收集新數據,製作一個笛卡爾產品,然後將這個新數據插入到表格3中。這樣,這個SQL語句就可以被刪除了。新的過程只需要幾秒鐘! 我認爲,當我們改進SQL語句,請首先確保這條SQL語句是絕對必要的。