对于索引视图来说,这听起来像是一个理想的方案,它使您可以在写时间而不是查询时间支付计算和聚合费用。
CREATE VIEW dbo.MyIndexedView
WITH SCHEMABINDING
AS
SELECT Enroll_Date, UserID, RawCount = COUNT_BIG(*)
FROM dbo.UserTable
GROUP BY Enroll_Date, UserID;
GO
CREATE UNIQUE CLUSTERED INDEX CIX_miv ON dbo.MyIndexedView(Enroll_Date, UserID);
这将花费一些时间来创建,并且当然需要在所有DML操作中进行维护,就像在基表上创建索引一样。
现在,针对该视图的查询将非常相似-视图中的每一行现在代表一个不同的用户/日期组合,因此可以通过单个COUNT(*)计算该图,而基表中的总行数为已经为您进行了部分汇总,现在您只需要使用每个日期的SUM进行累加即可:
SELECT Enroll_Date,
[Record #] = SUM(RawCount),
[User #] = COUNT(*)
FROM dbo.MyIndexedView WITH (NOEXPAND)
GROUP BY Enroll_Date;
在记住了this和this之后,添加了NOEXPAND提示。
我可以毫无疑问地告诉您,该查询将比您当前的查询快(但不会快多少),除了极少数情况下,您每个日期只有一个用户(在这种情况下,相同数量的数据将具有待读取),我们知道的列是基表索引中唯一的列。我们无法告诉您,在读取时间提高性能是否值得进行会影响工作负载的写入部分的额外工作-您必须测试一下以权衡取舍(没有索引是免费的)。
而且,如果您经常对Enroll_Date使用相同的通用WHERE子句来定义特定的,明确定义的范围(例如,当前的当前季度或当年),则可以添加匹配的过滤索引以进一步减少该I / O(但总会有一个交易)。
您可能还考虑在基表上放置聚簇索引。这似乎并不是从堆中受益的非常罕见的用例之一。