Fab*_*all 5 sql-server materialized-view azure-sql-database
首先,抱歉标题太长。
我将示例减少到最少,以使其更清晰,因此不再有有意义的语义。
DBMS:Azure SQL 数据库 V12。
假设有下表:
CREATE TABLE [dbo].[MuchDataTable](
[SmallDateTimeColumn] [smalldatetime] NOT NULL
)
GO
CREATE CLUSTERED INDEX [IX_MuchDataTable_SmallDateTimeColumn] ON [MuchDataTable] ([SmallDateTimeColumn])
Run Code Online (Sandbox Code Playgroud)
现在我想获取特定于任意天数范围的聚合数据。由于该表包含很多行(超过 150 Mio。)我创建了一个索引视图,它基本上如下所示:
CREATE VIEW [dbo].[AggregatedDateView]
WITH SCHEMABINDING
AS
SELECT CONVERT(DATE, [SmallDateTimeColumn]) AS [DateColumn], COUNT_BIG(*) AS [Count]
FROM [dbo].[MuchDataTable]
GROUP BY CONVERT(DATE, [SmallDateTimeColumn])
GO
CREATE UNIQUE CLUSTERED INDEX [IX_AggregatedDateView_Date] ON [dbo].[AggregatedDateView] ([DateColumn])
Run Code Online (Sandbox Code Playgroud)
对于我的一天分组,我将每个都转换DateTime
为Date
. 然后我在视图上创建一个聚集索引。
对视图执行简单的 SELECT * 扫描视图的索引。没关系:
但是,如果我在计算日期列上使用 WHERE 约束进行查询,则会对原始表执行聚集索引查找:
我的理解是,应该有一个 B 树,其中包含索引视图的所有转换日期。SQL Server 为什么选择扫描底层表的聚集索引?这对索引视图是不可能的,我必须在触发器和普通表之上构建解决方案吗?
编辑:为了更清楚地说明,一旦扫描了一系列日期,它就会成为一个真正的问题,所以像
SELECT * FROM [AggregatedDateView] WHERE [DateColumn] > '2016-05-20' AND [DateColumn] < '2016-08-20'
Run Code Online (Sandbox Code Playgroud)
这里扫描了超过 3 个月的索引,这对我来说已经很多了。
SQL Server 扩展视图并考虑访问基表。是否使用视图或基表是优化器基于成本的决定。
要强制 SQL Server 使用索引视图,您应该使用noexpand提示。
SELECT *
from [AggregatedDateView] WITH(NOEXPAND)
where [DateColumn] > '2016-05-20' AND
[DateColumn] < '2016-08-20'
Run Code Online (Sandbox Code Playgroud)