2016-08-16 61 views
0

我有一個簡單的select語句需要很長時間才能運行,但在同一個表上運行count(*)相同的WHERE子句在不到一秒的時間內返回。簡單的選擇查詢運行速度非常慢,但在運行速度非常快的同一個表上選擇count(*)

這個查詢了很長一段時間運行(1小時+):

SELECT col1 
     , col2 
     , col3 
    FROM Table 
    WHERE RowInsertDate >= @SomeStartDate 
    AND RowInsertDate < @SomeEndDate 

但此查詢回來在不到一秒鐘:

SELECT count(*) 
    FROM Table 
    WHERE RowInsertDate >= @SomeStartDate 
    AND RowInsertDate < @SomeEndDate  

表擁有34萬行,具有用於主鍵的ID列和地理區域(北,南,東,西)列。 「RowInsertDate」列是該行插入到表中的日期。上述查詢的預期結果分別爲「無行」和「0」。

此表的聚簇索引是(ID,geoRegion)ASC。此表在RowInsertDate ASC上也具有非聚集索引。

我不確定該從哪裏出發。有沒有人遇到過這個?

+0

可能是一個容量的事情。返回多少行? – Paparazzi

+0

這是一個執行計劃可以幫助我們的人。同樣,任何人都無法將選擇col1,col2與您正在注意的索引關聯起來,因爲我們不知道索引是否包含或不包含哪些列,所以我們不知道這是否正確或不正確。 – Matt

+0

這兩個查詢都是不同的,它會導致不同的執行計劃。您可以提供執行計劃 – TheGameiswar

回答

1

當您運行select count(*)時,SQL Server只能對您的索引中的行進行計數。當您運行select col1,col2,col3時,對於在索引中找到的每一行SQL Server都必須獲取聚簇索引鍵值(ID,geoRegion,存儲在索引中),然後使用該聚簇索引鍵值搜索表中找到的所有行。

如果SQL Server認爲爲聚簇索引執行所有查找將會更有效,SQL Server也可以決定執行聚簇索引掃描(或其他)。您可以檢查查詢計劃中會發生什麼。

爲了加快查詢速度,您可能需要考慮將需要選擇的列添加到RowInsertDate中,包括列或普通列。當然,如果列數相對較少(或者表中不會有很多更新),這當然是有意義的。

0

儘管您可以檢查執行計劃,但我很確定這是一個典型的BOOKMARK LOOKUP問題。這是資源消耗和耗時。一個解決方案是創建一個涵蓋索引來處理它。

這兩個查詢的執行時間是不同的,因爲它們完全不同。

當然,您還應該檢查列(col1,col2,col3)的數據類型。

除此之外,您還可以設置NOCOUNT ON。希望能幫助到你。

-2

由於查詢非常簡單。我認爲你缺少的是一個NOLOCK:

SELECT col1 
    , col2 
    , col3 
FROM Table (nolock) 
WHERE RowInsertDate >= @SomeStartDate 
AND RowInsertDate < @SomeEndDate 
+2

這是一個危險的推薦 – Paparazzi

+0

@Paparazzi:對於選擇查詢nolock是危險的如何? –

+0

@AnjaniKumarAgrawal http://blogs.sqlsentry.com/aaronbertrand/bad-habits-nolock-everywhere/ – scsimon

0

如果ID是唯一的(如身份證),那麼我建議你做的是,PK單獨聚。額外的列必須攜帶額外的數據才能進行查找。

我和我希望geoRegion是一個字節。如果varchar,那麼你攜帶的數量是你需要的10倍。這是相同內存量的1/10。

如果上述不能解決問題然後添加包括在索引

CREATE NONCLUSTERED INDEX IX_Table_RowInsertDate 
ON Table (RowInsertDate) 
INCLUDE (col1, col2, col3); 
0

對不起在響應延遲的那些列。

它看起來像服務器本身有問題;我們的日誌充滿了IO問題。我們讓DBA重新啓動服務器,現在查詢運行得很快。

我不確定確切問題的性質是什麼,但現在已經解決。如果同樣的事情再次出現,我會發布另一個問題。

相關問題