Ala*_*ain 6 sql-server optimization materialized-view sql-server-2016
我有一个索引视图的适度用例,它折叠一列并总结一个大表中的所有条目:
CREATE VIEW dbo.Losses_CombinedPortfolio WITH SCHEMABINDING
AS
SELECT [Category], [Year],
SUM(ISNULL(Loss,0)) AS [Loss], COUNT_BIG(*) as [Count]
FROM dbo.Sub_Portfolio_Losses
GROUP BY [Category], [Year]
GO
CREATE UNIQUE CLUSTERED INDEX Idx
ON dbo.Losses_CombinedPortfolio([Category], [Year]);
Run Code Online (Sandbox Code Playgroud)
我最初的目标更加雄心勃勃,但索引视图的限制如此之多......我很高兴能够让它发挥作用。
可悲的是,当我尝试对此索引视图进行基本查询时:
SELECT TOP (100) *
FROM Losses_CombinedPortfolio
ORDER BY Loss DESC
Run Code Online (Sandbox Code Playgroud)
...查询也很慢,实际执行计划表明它总是回到源表并每次从头开始计算聚合:
我只能假设这是因为我计算出的“损失”列没有被具体化 - 但这会让我感到惊讶,因为聚集索引创建成功。
请注意,此视图的主要用例是按Loss
降序排序,但我无法明确创建包含它的索引:
CREATE UNIQUE CLUSTERED INDEX Idx
ON dbo.Losses_CombinedPortfolio
(Category, Loss DESC, [Year]);
Run Code Online (Sandbox Code Playgroud)
我收到错误:
无法在视图 'dbo.Losses_CombinedPortfolio' 上创建索引或统计信息 'Idx',因为关键列 'Loss' 是不精确的、已计算的且未持久化。考虑删除对视图索引或统计键中的列的引用或更改列以使其精确。如果在基表中计算列,请考虑在那里将其标记为 PERSISTED。
我尝试通过将总损失转换为除float
(甚至尝试将其截断为bigint
)以外的类型来解决“不精确”,但似乎此错误源于用于计算总和的基础类型。
我很困惑 - 我看到其他问题声称他们能够成功地执行聚合,例如sum
在他们的索引视图中,所以我不确定为什么这不起作用。
J.D*_*.D. 13
您需要使用NOEXPAND
查询提示(我假设您使用的是 SQL Server 标准版),以便您的查询使用索引视图(而不是将其扩展到基础表)。这将解决您的第一个问题。
这是您在查询中使用它的方式:
SELECT TOP (100) *
FROM Losses_CombinedPortfolio WITH (NOEXPAND)
ORDER BY Loss DESC
Run Code Online (Sandbox Code Playgroud)
您可以在Microsoft的查询提示文档中查看更多信息。但这是与您当前遇到的相关的部分:
仅当在查询的 SELECT 部分直接引用视图并且指定了 WITH (NOEXPAND) 或 WITH (NOEXPAND, INDEX( index_value [ ,...n ] ) ) 时,索引视图才不会展开。
这是您可以使用的少数查询提示之一,而不必担心它是不好的做法,实际上,出于某些原因也建议使用它。
至于用“不精确”错误您的问题,这是因为你猜对了,由于Loss
FLOAT类型的塔中(这是不准确的)。即使铸造它也无济于事;您必须先将基础类型更改为精确的类型,然后才能在视图中对其进行索引。(例如,如果您可以将数据类型更改为 DECIMAL,那么您就可以将该列添加到您的索引中。)
从文档:
任何浮点数或实数表达式都被认为是不精确的,不能作为索引的键;一个浮动或真实表达可以在索引视图但不作为密钥来使用。对于计算列也是如此。如果任何函数、表达式或用户定义的函数包含任何浮点或实数表达式,则它被认为是不精确的。这包括逻辑的(比较)。
归档时间: |
|
查看次数: |
227 次 |
最近记录: |