2012-05-29 192 views
0

我有以下SQL這需要很長的時間來執行,有沒有寫這個改善的速度沒有更好的辦法。提高SQL查詢速度

任何幫助是非常可觀的。

感謝

SELECT a.KeyField 
    FROM Details a, 
     Master b 
    WHERE a.ForeignKeyField = b.ForeignKeyField 
     AND a.KeyField IS NOT NULL 
     AND Date BETWEEN 
TO_DATE ('01-01-2011', 'dd-mm-yyyy') AND TO_DATE ('31-12-2011', 'dd-mm-yyyy') 
     AND a.KeyField IN 
     (SELECT p.KeyField 
     FROM Details p, 
       Master q 
     WHERE q.ForeignKeyField = p.ForeignKeyField 
      AND p.KeyField IS NOT NULL 
      AND p.KeyField = a.KeyField 
      AND q.FKField2 = b.FKField2 
     GROUP BY p.KeyField, 
        q.Date HAVING COUNT (DISTINCT q.ForeignKeyField) > 1) 
    GROUP BY b.Id, 
      b.Name, 
      b.ForeignKeyField, 
      b.Date, 
      a.ForeignKeyField, 
      a.SomeOtherField, 
      a.KeyField, 
      b.EtcEtc 
+1

喜歡JOIN到的連接表,始終做到'SmallTable INNER JOIN BigTable'。 – MPelletier

+0

@MPelletier很棒的信息!你能解釋爲什麼SmallTable INNER JOIN BigTable –

+0

你的索引是什麼? – HLGEM

回答

1

首先,你需要學會正確的聯接語法。我的猜測是Oracle由於相關的子查詢而選擇了次優查詢路徑。讓我們把它變成一個連接,而不是:

SELECT a.KeyField 
FROM Details a join 
Master b 
on a.ForeignKeyField = b.ForeignKeyField join 
(SELECT p.KeyField, q.Date, q.FKField2 
    FROM Details p join 
     Master q 
     on q.ForeignKeyField = p.ForeignKeyField 
    WHERE p.KeyField IS NOT NULL AND 
     q.FKField2 = b.FKField2 
    GROUP BY p.KeyField, q.Date 
    HAVING COUNT (DISTINCT q.ForeignKeyField) > 1 
) t 
on a.KeyField = t.KeyField and 
    b.FKField2 = t.FKField2 
WHERE a.KeyField IS NOT NULL AND 
    Date BETWEEN TO_DATE ('01-01-2011', 'dd-mm-yyyy') AND TO_DATE ('31-12-2011', 'dd-mm-yyyy') AND 
GROUP BY b.Id, b.Name, b.ForeignKeyField, b.Date, a.ForeignKeyField, a.SomeOtherField, a.KeyField, 
    b.EtcEtc 

寫作這種方式也讓我認識到,有在日期沒有條件,儘管這是在子查詢中使用。它是否正確?

+0

日期時間用於外部查詢,因爲我有條件'entry_date BETWEEN' – user75ponic

+0

有了JOIN,而不是在哪裏提高了速度,明天我會爲結果做一個徹底的測試。非常感謝。 – user75ponic

+0

當我做了一個小測試時,我注意到有很多用查詢檢索到的行。這是因爲當我執行時,我從查詢中刪除了sh_status_code部分?但我會做一個徹底的測試。 – user75ponic

0

請確保您有相關的指標到位。檢查執行計劃以確認它們實際上正在使用。 Oracle在選擇索引時相當挑剔。

1

您的查詢運行EXPLAIN,你會看到那裏的緩慢的來源。但是,一般情況下,如果您可以避免嵌套查詢(您的IN語句)和DISTINCT,則查詢的性能會更好。看看你是否可以在同一個查詢中加入DetailsMaster表格兩次,並相應地放置索引

0

我不明白內部查詢的原因。我將簡化這樣的:

SELECT a.KeyField 
FROM Details a, 
    Master b 
WHERE a.ForeignKeyField = b.ForeignKeyField 
    AND a.KeyField IS NOT NULL 
    AND Date >= TO_DATE ('01-01-2011', 'dd-mm-yyyy') 
    AND Date <= TO_DATE ('31-12-2011', 'dd-mm-yyyy') 

GROUP BY b.Id, 
     b.Name, 
     b.ForeignKeyField, 
     b.Date, 
     a.ForeignKeyField, 
     a.SomeOtherField, 
     a.KeyField, 
     b.EtcEtc 
HAVING COUNT (DISTINCT q.ForeignKeyField) > 1 

>=, <=更換BETWEEN將有助於

+1

不要鼓勵隱式連接的sql反模式 – HLGEM

+0

你能解釋一下反模式? –

+0

順便說一下,我非常尊重你,原因如下:1.你在過去幫助過很大,2.你不害怕提問(即使其他用戶有高分)3。你沒有一個用來隱藏你的低調回答的幽靈帳戶,不像其他高調用戶 –