2014-04-25 145 views
3

我有一張近300萬行的表,每秒有5-10次更新/插入。每行都分配一個類別,並且我想按類別分組以計算每個類別的總行數。SQL Group By with Count很慢

Select CategoryId 
    , COUNT(*) as TotalRows 
    FROM Table1 
WHERE SaleTypeId = 2 AND CategoryId > 1 
GROUP BY CategoryId 

表模式:

CREATE TABLE [dbo].[Table1](
[SaleId]  INT IDENTITY (1, 1) NOT NULL, 
[SaleTypeId] INT     NOT NULL, 
[CategoryId] INT     NULL) 

主鍵:

ADD CONSTRAINT [PK_Table1] 
PRIMARY KEY CLUSTERED ([SaleId] ASC) 
WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, 
     IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF); 

我有表的一個非聚集索引:

CREATE NONCLUSTERED INDEX [Index1] ON [dbo].[Table1] 
(
    [SaleTypeId] ASC, 
    [CategoryId] ASC  
) 

查詢計劃:

enter image description here

查詢需要40到60秒來運行,它看起來像大量數據在索引被讀取查找操作。有什麼辦法可以加快這個查詢嗎?我讀過數據越大,計數越慢,並且有更快的方法來計算整個表的數量,但是我需要按類別計數。

+0

添加聚集索引肯定會有所幫助。 –

+1

該圖顯示索引查找發生在Table1.Index1上,該索引不是idx_SaleCategory。看起來你沒有從你的新索引中獲益。 – sarin

+0

@ M.Ali - 它會幫助這個查詢_但是可能是整體聚集索引的一個不好的選擇。 –

回答

1

反轉列要想在非聚集索引,就像這樣:

CREATE NONCLUSTERED INDEX [Index1] ON [dbo].[Table1] 
(
    [CategoryId] ASC,  
    [SaleTypeId] ASC 
) 
+0

你爲什麼推薦這個?據我所知,索引中應首先使用等式列,其次是不等列。當我使用反向索引運行查詢時,執行計劃建議創建原始索引。 – jtiger

+0

你看過這個索引,看它是否分散很多,需要重建嗎? –

+0

我推薦它,因爲'SaleType = 2'似乎不太有選擇性。現在的密度並不值得嘗試。問題是你必須閱讀(按順序)大部分索引,一個或另一個;沒有其他方法可以對CategoryId上的聚合進行計數,無論如何,這兩列應該有一個NC指數,哪一個只是選擇性問題。 – dean

0

嘗試運行此,我還要把作爲@dean建議指標

Select CategoryId, COUNT(CategoryId) as TotalRows 
FROM Table1 WITH (NOLOCK) 
WHERE SaleTypeId = 2 AND CategoryId > 1 
GROUP BY CategoryId 
0

我結束了運行此作爲每晚聚合作業並將結果存儲在一個聚合表中。它沒有提供最新的結果(經過深思熟慮後,我們可以忍受),夜間查詢也不會更快,但是從聚合表中讀取要快得多。