sql - 如何模拟索引 View 中的不同计数?

标签 sql sql-server tsql indexing aggregate-functions

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

我正在使用索引顾问来帮助确定索引真正有用的地方,而不会过度索引我的数据库。

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

我在尝试为我的一个表制作索引 View 时遇到了一个令人费解的错误。
这是我的数据库中非常常见的场景,因此我想知道是否有一个全面的通用解决方案,我可以在需要的地方重新调整用途。

我收到的错误如下所示:

Msg 10126, Level 16, State 1, Line 12
Cannot create index on view "Database.dbo.vwCountDistinctExampleIX" because it uses aggregate "COUNT_BIG" with the DISTINCT keyword.
...
Consider use of a GROUP BY or COUNT_BIG(*) view to simulate DISTINCT on grouping columns.

当我需要 COUNT_BIG (DISTINCT {expression} ) 时,就会出现问题,这在索引 View 中显然是不允许的。
该错误消息似乎暗示您可以模拟 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 AS t1
    INNER JOIN dbo.Table2 AS t2 ON t2.Field1 = t1.ID

GROUP BY
    t1.ID

GO

/* Error here: Cannot create index on view "Database.dbo.vwCountDistinctExampleIX" because it uses aggregate "COUNT_BIG" with the DISTINCT keyword. */
CREATE UNIQUE CLUSTERED INDEX [PK vwCountDistinctExampleIX ID]  ON vwCountDistinctExampleIX ( [ID] )

CREATE INDEX [IX vwCountDistinctExampleIX DistinctTotal ON vwCountDistinctExampleIX ( DistinctTotal )

GO

最佳答案

我认为您无法直接在索引 View 中实现您想要的目标。但是,如果 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

关于sql - 如何模拟索引 View 中的不同计数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31215809/

相关文章:

sql-server - sql server 可选参数 : syntax for between clause

mysql - 在perl中按换行符划分数组内容

sql-server - 无法在 Sql Server 表中将身份规范更改为"is"

c# - ‘帮助’ 服务器无法生成主键列

sql - 如何在 SQL Server 2005 中的一条语句中更新两个表?

sql - 从存储在 SQL Server 表中的数据中获取上个月的日期值

SQL Server TSQL 调试 - 海量 View - 有什么技巧吗?

sql - 如何在 Oracle 的过程中创建表?

java - 在 MySql 表中插入特定类型的文本时出现问题

sql - T-SQL - 逐字符比较字符串