2014-03-04 69 views
0

我想優化一個由前同事編寫的緩慢運行的查詢。他沒有使用存儲過程,並直接在ADO.NET中編寫查詢,查詢速度太慢。需要優化計數查詢

我試圖將查詢轉換爲單個SP。這個特殊的SELECT聲明需要很長時間。 @PMasterTable被使用邏輯在最後一個條件內被使用了太多次。

INSERT INTO @PMasterTable 
SELECT R.PId 
    FROM PRecord R 
    WHERE R.PId IN(@aId , @nId) 

SELECT @DeleteCount = COUNT(P.Id) 
    FROM Result P 
    WHERE(P.Approved IS NULL 
    OR P.Approved = 0) 
    AND P.ACTION = 'D' 
    AND P.Id NOT IN(SELECT Id FROM ARecords) 
    AND P.PId IN(SELECT PId FROM @PMasterTable); 

我寫了SQL查詢已經有一段時間了,所以我有點生疏了!

+1

你有沒有做過任何形式的查詢計劃的分析?它是否緩慢,因爲你的索引不好? – Dismissile

+0

還沒有,我首先將查詢轉換爲SP,幾乎所有查詢都是上述SELECT查詢的某種變體。我認爲查詢在NOT IN/IN條件下花費時間會導致結果很大。 – RCuber

+0

你是否使用臨時表而不是變量? – Roshan

回答

0
SELECT @DeleteCount = COUNT(P.Id) 
    FROM Result P 
    join @PMasterTable 
    on @PMasterTable.PId = P.PId 
    and ( P.Approved IS NULL 
     OR P.Approved = 0) 
    AND P.ACTION = 'D' 
    left join ARecords 
    on ARecords.Id = P.Id 
where ARecords.Id is null 

而且我覺得COUNT(*)會在這裏

相同的答案,而不@PMasterTable

SELECT @DeleteCount = COUNT(P.Id) 
    FROM Result P 
    join PRecord R 
    on r.PId = P.PId 
    and ( P.Approved IS NULL 
     OR P.Approved = 0) 
    and P.ACTION = 'D' 
    and r.PId IN(@aId , @nId) 
    left join ARecords 
    on ARecords.Id = P.Id 
where ARecords.Id is null 

通過拉動條件爲加入查詢優化器似乎與做的更好儘早過濾。
特別是那個和r.PId IN(@aId,@nId)最有可能是你想要提前申請的。

並根據索引和表大小,那麼這可能會更快(刪除r.PId)

and P.PId IN(@aId , @nId) 
+0

你不是試圖加入一個TempTable [@PMasterTable],它甚至不會在這個實例中被創建嗎? – Talspaugh27

+0

@ Talspaugh27如果PMasterTable不可用,那爲什麼插入工作? – Paparazzi

+0

在原來插入INTO @PMastertable然後使用該表來加入選定的值。最好不要填充該臨時表並嚴格從查詢的值本身開始。 你是對的,表已被宣佈,但沒有填充,對不起,我錯過了我的評論。 – Talspaugh27

0

結合2個查詢只需要你將其更改爲(不通過SQL運行這解析它)

SELECT @DeleteCount = COUNT(P.Id) 
FROM Result P 
inner join PRecord R on R.PId = P.PId 
    and R.PId IN(@aId , @nId) 
WHERE isnull(P.Approved, 0) = 0 
AND P.ACTION = 'D' 
AND P.Id NOT IN(SELECT Id FROM ARecords) 

不幸的是,這可能不會解決您的速度問題。被收錄在「結果」表和一般recommandation根據您的查詢「PRecord」表

0

哪些列:

替換爲空或= X由ISNULL(變量X)= X。它可能更改您的執行計劃並解決問題 通過not exists(query where column = Value)將您的值替換爲(查詢)。存在的停止在條件完成時搜索你的值,而不是在查詢結束時它可以加速。

但這是一般的建議,它不應該解決一個大問題。 最後一個,有時需要避免執行計劃的問題,但是你知道爲什麼你有2個查詢而不是最後一個子查詢嗎? 你在其他地方使用其他表嗎?

下面是代碼

SELECT @DeleteCount = COUNT(P.Id) 
    FROM Result P 
    inner join PRecord R on r.pid = p.pid 
    WHERE isnull(P.Approved,0) = 0 
    AND P.ACTION = 'D' 
    AND not exists (SELECT * FROM ARecords as a where a.ID = P.Id) 
    and R.PId IN(@aId , @nId) 
0

使用 「IN」 或 「NOT IN」 與子查詢可能導致性能問題。然後你並不需要子查詢中的數據,因爲你只是檢查這個值是否存在。

試試這個:

SELECT @DeleteCount = COUNT(P.Id) 
    FROM Result P 
    WHERE(P.Approved IS NULL 
    OR P.Approved = 0) 
    AND P.ACTION = 'D' 
    AND NOT EXISTS (
     SELECT 1 FROM ARecords AR WHERE AR.ID= P.Id) 
    AND EXISTS (
     SELECT 1 FROM @PMasterTable PM WHERE PM.PId = P.PId);