2014-06-30 100 views
0

由於Oracle上的大量數據,我正在努力優化查詢。SQL子查詢和聯接給出相同或不同的結果(oracle)

有一個像這樣的查詢。

隨着子查詢:

SELECT 
    STG.ID1, 
    STG.ID2 
FROM (SELECT 
     DISTINCT 
     H1.ID1, 
     H2.ID2 
     FROM T_STGDV STG 
     INNER JOIN T_HUB1 H1 ON STG.BK1 = H1.BK1 
     INNER JOIN T_HUB2 H2 ON STG.BK2 = H2.BK2) STG 
LEFT OUTER JOIN T_LINK L ON L.ID1 = STG.ID1 AND L.ID2 = STG.ID2 
WHERE L.IDL IS NULL; 

我這樣做的優化:

SELECT 
    DISTINCT 
    H1.ID1, 
    H2.ID2 
FROM T_STGDV STG 
INNER JOIN T_HUB1 H1 ON STG.BK1 = H1.BK1 
INNER JOIN T_HUB2 H2 ON STG.BK2 = H2.BK2 
LEFT OUTER JOIN T_LINK L ON L.ID1 = H1.ID1 AND L.ID2 = H2.ID2 
WHERE L.IDL IS NULL; 

我想知道結果會是一樣的,行爲是相同的。

我做了一些測試,我沒有發現差異,但也許我錯過了一些測試用例?

任何想法這些查詢之間可能有什麼區別?

謝謝。

一些細節,解釋這些測試表計劃(成本並不能代表真正的表)

第一個查詢:

Plan hash value: 2680307749 

----------------------------------------------------------------------------------- 
| Id | Operation    | Name | Rows | Bytes | Cost (%CPU)| Time  | 
----------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT  |   |  1 | 65 | 11 (28)| 00:00:01 | 
|* 1 | FILTER     |   |  |  |   |   | 
|* 2 | HASH JOIN OUTER  |   |  1 | 65 | 11 (28)| 00:00:01 | 
| 3 | VIEW     |   |  1 | 26 |  8 (25)| 00:00:01 | 
| 4 |  HASH UNIQUE   |   |  1 | 134 |  8 (25)| 00:00:01 | 
|* 5 |  HASH JOIN   |   |  1 | 134 |  7 (15)| 00:00:01 | 
|* 6 |  HASH JOIN   |   |  1 | 94 |  5 (20)| 00:00:01 | 
| 7 |  TABLE ACCESS FULL| T_STGDV |  1 | 54 |  2 (0)| 00:00:01 | 
| 8 |  TABLE ACCESS FULL| T_HUB1 |  2 | 80 |  2 (0)| 00:00:01 | 
| 9 |  TABLE ACCESS FULL | T_HUB2 |  2 | 80 |  2 (0)| 00:00:01 | 
| 10 | TABLE ACCESS FULL | T_LINK |  3 | 117 |  2 (0)| 00:00:01 | 
----------------------------------------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    1 - filter("L"."IDL" IS NULL) 
    2 - access("L"."ID2"(+)="STG"."ID2" AND "L"."ID1"(+)="STG"."ID1") 
    5 - access("STG"."BK2"="H2"."BK2") 
    6 - access("STG"."BK1"="H1"."BK1") 

Note 
----- 
    - dynamic sampling used for this statement (level=2) 

第二查詢

Plan hash value: 2149614538 

----------------------------------------------------------------------------------- 
| Id | Operation    | Name | Rows | Bytes | Cost (%CPU)| Time  | 
----------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT  |   |  1 | 65 | 11 (28)| 00:00:01 | 
| 1 | HASH UNIQUE   |   |  1 | 65 | 11 (28)| 00:00:01 | 
|* 2 | FILTER    |   |  |  |   |   | 
|* 3 | HASH JOIN OUTER  |   |  1 | 65 | 10 (20)| 00:00:01 | 
| 4 |  VIEW    |   |  1 | 26 |  7 (15)| 00:00:01 | 
|* 5 |  HASH JOIN   |   |  1 | 134 |  7 (15)| 00:00:01 | 
|* 6 |  HASH JOIN   |   |  1 | 94 |  5 (20)| 00:00:01 | 
| 7 |  TABLE ACCESS FULL| T_STGDV |  1 | 54 |  2 (0)| 00:00:01 | 
| 8 |  TABLE ACCESS FULL| T_HUB1 |  2 | 80 |  2 (0)| 00:00:01 | 
| 9 |  TABLE ACCESS FULL | T_HUB2 |  2 | 80 |  2 (0)| 00:00:01 | 
| 10 |  TABLE ACCESS FULL | T_LINK |  3 | 117 |  2 (0)| 00:00:01 | 
----------------------------------------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    2 - filter("L"."IDL" IS NULL) 
    3 - access("L"."ID2"(+)="H2"."ID2" AND "L"."ID1"(+)="H1"."ID1") 
    5 - access("STG"."BK2"="H2"."BK2") 
    6 - access("STG"."BK1"="H1"."BK1") 

Note 
----- 
    - dynamic sampling used for this statement (level=2) 
+0

他們長得很像我。我的建議是比較他們的執行計劃。我希望他們是相似的,但誰知道。 – AndreySarafanov

+0

是的,有非常相似的...尤其是執行連接的順序。但第二個查詢速度快20倍... – MisterT

回答

0

查詢看起來與我相當,因爲where條款。

沒有where子句,它們不等價。重複在t_link(相對於join鍵)會導致重複的行。但是,您正在尋找沒有匹配,所以這不是一個問題。當沒有匹配時,這兩個版本應該是等價的。

0

如果您想用當前數據集測試它們,您可以使用減號。

查詢1個 MINUS 查詢2

如果顯示任何的結果,它們是不相同的。

你要翻轉他們周圍嘗試過其他方式...

查詢2 減號 查詢1

如果兩個測試返回任何記錄,查詢對你目前的效果相同數據集。

+0

我用減號做了測試,但我不想錯過任何測試用例......我所有的減號測試都是空的,但是......可能有一種情況不適用。 。 – MisterT

+0

如果T_LINK.ID1和T_LINK.ID2是唯一的,則不應該有問題。如果在T_LINK中有兩個記錄具有相同的ID1和ID2,並且IDL在兩者上均爲空,則第一個查詢將顯示兩次相同的ID1和ID2,因爲distinct是在子查詢中,而不是在主要select中作爲它在你的第二個查詢中,所以你的第二個查詢只會返回一個記錄。 – Bob

+0

是的,我的目標T_LINK在ID1和ID2上有唯一索引。 – MisterT

0

這可能是區別:看看這些線在你執行計劃:

2 - access("L"."ID2"(+)="STG"."ID2" AND "L"."ID1"(+)="STG"."ID1") 

3 - access("L"."ID2"(+)="H2"."ID2" AND "L"."ID1"(+)="H1"."ID1") 

STG是Oracle在查詢期間創建的臨時表(即T_STGDV別名和子查詢別名之間的含糊不清僅僅是重寫查詢的原因)。而這張臨時表格當然是無索引的。重構後,Oracle優化器開始加入T_LINKH1H2而不是臨時表,並允許它利用建立在這些表上的索引,從而使您的速度提高20倍。

0

經過測試,結果一致。第二個更有效率。

相關問題