2015-05-29 90 views
1

我試圖從非常大的Audits表(數百萬行)檢索數據。所以我需要儘可能高效地運行查詢。 首先我有一個子查詢打返回ObjectTypeId並以此來限制對審計表SQL慢子查詢

這個查詢花費4分鐘運行查詢:

select distinct Audits.ObjectTypeID, COUNT(*) as Count 
from Audits as Audits 
where Audits.ObjectTypeID = 
(select distinct ObjectType.ObjectTypeID from ObjectType where ObjectName = 'Data') 
group by Audits.ObjectTypeID 

如果我在ObjectTypeID默認查詢運行在42秒

select distinct(Audits.ObjectTypeID), COUNT(*) as Count 
from Audits 
where Audits.ObjectTypeID = 1 
group by Audits.ObjectTypeID 

但是,當單獨運行子查詢僅只需第二運行。那麼爲什麼第一個查詢需要這麼長時間呢?

+0

你能提供,匿名從SQL事件探查器輸出(?)?或更好地提供*實際*,不是預期的執行計劃? – matcheek

+0

你有'ObjectType.ObjectName'和'Audits.ObjectTypeID'上的索引嗎? –

+0

是否有多個記錄具有'Data'的ObjectName?如果不是,那麼你可以拿出「DISTINCT」,看看是否會產生更有效的計劃。 –

回答

1

我可以看到三件事情可以幫助:

  1. ObjectTypeID到一個變量:因爲應該只有一個值,它
  2. 在這兩個查詢取出DISTINCT,因爲他們應該是不必要的(子查詢應該只有一個值,你是該值在外部查詢分組
  3. 取出GROUP BY,因爲你只查詢一個ObjectTypeID

所以最終的查詢是:

DECLARE @ObjectTypeID INT 

SELECT @ObjectTypeID = (select ObjectType.ObjectTypeID 
         from ObjectType 
         where ObjectName = 'Data') 

select Audits.ObjectTypeID, COUNT(*) as Count 
from Audits as Audits 
where Audits.ObjectTypeID = @ObjectTypeID 

如果您要執行這個作爲一個單獨的語句,而不是一個批處理或存儲過程(這意味着你不能使用變量)thne你可以保持子查詢:

select Audits.ObjectTypeID, COUNT(*) as Count 
from Audits as Audits 
where Audits.ObjectTypeID = 
    (select ObjectType.ObjectTypeID 
    from ObjectType 
    where ObjectName = 'Data') 
+0

那麼有多於1個相同的'ObjectTypeID'的情況呢? –

+0

爲什麼不在兩個表之間進行簡單的連接?事實上,第二個查詢就相當於這個。至於第一個查詢,它與查詢優化器爲連接案例做的沒有什麼不同 –

+0

@JohnOdom然後,問題中的原始查詢將失敗。 –

1

,你所得到的最性能損失可能是這一行的部分:

where Audits.ObjectTypeID = 
(select distinct ObjectType.ObjectTypeID from ObjectType where ObjectName = 'Data') 

你實際上是調用同曲在你的表的每一行上,它將搜索整個表格ObjectType並返回該子查詢的整個結果。如果您的ObjectType表格很大,這將會是一個很大的表現。您可以通過使用EXISTS來加快查詢的該部分,以便在找到結果後它會提前返回。這裏有一個例子:

SELECT a.ObjectTypeID, COUNT(*) as Count 
FROM Audits a 
WHERE EXISTS 
(
    SELECT ot.ObjectTypeID 
    FROM ObjectType ot 
    WHERE ot.ObjectName = 'Data' AND ot.ObjectTypeID = a.ObjectTypeID 
) 
GROUP BY a.ObjectTypeID 
+0

不需要'DISTINCT'子句。分組只會爲分組字段的每個組合返回一行 –

+0

@PanagiotisKanavos你是對的,我忘了。謝謝。 –

+2

@JohnOdom你確定子查詢爲每一行運行嗎?我似乎記得編譯器會將它識別爲單值查詢(意味着它不依賴於外部查詢中的任何數據)並且只執行一次,但我可能是錯的。 –

0

你可以試試這個

SELECT DISTINCT Audits.ObjectTypeID, COUNT(*) as Count 
FROM Audits as Audits 
INNER JOIN 
(SELECT DISTINCT ObjectTypeId, ObjectName FROM ObjectType 
WHERE ObjectName = 'Data') as ObjectType ON Audits.ObjectTypeID = ObjectType.ObjectTypeID 
GROUP BY Audits.ObjectTypeID 
+0

這不會更快,謝謝 – Juninho

+0

SELECT DISTINCT Audits.ObjectTypeID,COUNT(*)作爲計數 FROM審計作爲審計 INNER JOIN ObjectType作爲ObjectType ON Audits.ObjectTypeID = ObjectType.ObjectTypeID AND ObjectType。ObjectName ='Data' GROUP BY Audits.ObjectTypeID –