如何在索引视图中模拟count不同?

时间:2015-07-04 00:53:06

标签: sql sql-server tsql indexing aggregate-functions

我正在使用Microsoft SQL Azure v12.0中托管的数据库

我使用索引顾问程序帮助确定索引真正有用的位置,而不会过度索引我的数据库。

我遇到的情况是,每当有人运行查询时,索引视图确实有助于消除GROUP BY大量数据的需要。

在尝试为我的一张桌子制作索引视图时,我遇到了一个令人费解的错误 这是我数据库中非常常见的情况,所以我想知道是否有一个全面的通用解决方案,我可以在任何需要的地方重新使用。

我收到的错误如下:

  

Msg 10126,Level 16,State 1,Line 12
  无法在视图上创建索引" Database.dbo.vwCountDistinctExampleIX"因为它使用了聚合" COUNT_BIG"使用DISTINCT关键字。
  ...
  考虑使用GROUP BYCOUNT_BIG(*)视图模拟分组列上的DISTINCT

当我需要COUNT_BIG ( DISTINCT {expression} )时,问题就出现了,这在索引视图中显然是不允许的 错误消息似乎暗示您可以模拟COUNT DISTINCT行为并使用DISTINCT获得相同的结果而不使用,这将非常好,因为它允许我索引该列并再次帮助消除常见查询中的另一种昂贵的GROUP BY子句(因为执行计划只能引用索引而不是反复重组表数据)。

我真的不明白COUNT_BIG ( * )在这种情况下是如何运作的,所以我不明白错误信息的建议是什么。
有没有一种方法可以在不使用DISTINCT的情况下获得此聚合值,同时仍然可以索引聚合列?

CREATE VIEW [vwCountDistinctExampleIX] WITH SCHEMABINDING AS SELECT
                                         [T1].[ID]            ,
    COUNT_BIG ( DISTINCT [T2].[Field2] ) AS   [DistinctTotal] ,
    COUNT_BIG ( * )                      AS   [CountStar]

    FROM [dbo].[Table1] [T1]
    JOIN [dbo].[Table2] [T2] ON [T2].[Field1] = [T1].[ID]

    GROUP BY [T1].[ID]
GO

CREATE UNIQUE CLUSTERED INDEX [PK vwCountDistinctExampleIX ID] -- Error here
                           ON [vwCountDistinctExampleIX] ( [ID] )

CREATE                  INDEX [IX vwCountDistinctExampleIX DistinctTotal]
                           ON [vwCountDistinctExampleIX] ( [DistinctTotal] )
GO

2 个答案:

答案 0 :(得分:2)

我认为你不能在索引视图中直接达到你想要的效果。但是,如果Table2中的行数很大,但Field2中的不同值的数量不是很大,则以下方法可能会有所帮助:

CREATE TABLE Table1 (ID INT PRIMARY KEY)
CREATE TABLE Table2 (Field1 INT NOT NULL REFERENCES Table1, Field2 INT NOT NULL)

INSERT INTO Table1 VALUES (1),(2),(3)
INSERT INTO Table2 VALUES (1,10),(1,20),(1,20),(2,30)

GO
CREATE VIEW dbo.IndexedView1 
WITH SCHEMABINDING AS
SELECT ID, Field2, COUNT_BIG(*) AS Cnt
FROM dbo.Table1 T1
INNER JOIN dbo.Table2 T2 ON T1.ID = T2.Field1
GROUP BY ID, Field2

GO
CREATE UNIQUE CLUSTERED INDEX PK_IndexedView1 ON IndexedView1 (ID, Field2)

GO
CREATE VIEW SimpleView2
AS
SELECT ID, COUNT_BIG(*) AS DistinctTotal, SUM(Cnt) AS CountStar
FROM dbo.IndexedView1 X
GROUP BY ID

答案 1 :(得分:1)

您可以通过对两列进行分组来部分索引此查询:

GROUP BY [T1].[ID], [T2].[Field2]

查询处理器非常智能,现在可以使用索引来计算不同的。

显然,这种观点的效率低于你想要的效果,但总比没有好。