这是尝试改善Max Vernon的解决方法。在他的解决方案中,他建议在视图和统计对象上使用2个索引。
第一个索引是聚簇的,这实际上是必需的,因为与表上的非聚簇索引不同,如果尝试在不首先具有聚簇索引的情况下尝试在视图上创建非聚簇索引,则会产生错误。
第二索引是非聚集索引,用作查询后面的索引。在他的回答的评论部分,我问如果使用聚集索引而不是非聚集索引会发生什么。
下面的分析试图回答这个问题。
我正在使用与他完全相同的代码,除了没有在视图上创建非聚集索引。
我也没有创建统计对象。如果您遵循此方法并使用SQL Server Management Studio(SSMS)输入以下代码,则应注意,您可能会看到一些红色的波浪线-看起来像错误。这些(可能)不是错误,但是涉及智能感知问题。
您可以禁用智能感知,也可以忽略错误并运行命令。它们应该正确完成。
-- Create the test table that uses a computed column.
USE tempdb;
CREATE TABLE dbo.PersistedViewTest
(
PersistedViewTest_ID INT NOT NULL
CONSTRAINT PK_PersistedViewTest
PRIMARY KEY CLUSTERED
IDENTITY(1,1)
, SomeData VARCHAR(2000) NOT NULL
, TestComputedColumn AS (PersistedViewTest_ID - 1) PERSISTED
);
GO
-- Insert some test data into the table.
INSERT INTO dbo.PersistedViewTest (SomeData)
SELECT o.name + o1.name + o2.name
FROM sys.objects o
CROSS JOIN sys.objects o1
CROSS JOIN sys.objects o2;
GO
针对表运行以下查询后,将产生以下执行计划(无视图/索引视图):
SELECT pv.PersistedViewTest_ID, pv.TestComputedColumn
FROM dbo.PersistedViewTest pv
WHERE pv.TestComputedColumn = CONVERT(INT, 26)
GO
这提供了一个比较基准。请注意,查询完成后,将创建一个统计对象(_WA_Sys_00000003_1FCDBCEB)。创建聚簇表索引时,将创建PK_PersistedViewTest统计对象。
接下来,创建过滤视图和该视图上的聚簇索引:
-- Create filtered view on the computed column.
CREATE VIEW dbo.PersistedViewTest_View
WITH SCHEMABINDING
AS
SELECT PersistedViewTest_ID, SomeData, TestComputedColumn
FROM dbo.PersistedViewTest
WHERE TestComputedColumn < CONVERT(INT, 27);
GO
-- Create unique clustered index to persist the values, including the computed column.
CREATE UNIQUE CLUSTERED INDEX IX_PersistedViewTest
ON dbo.PersistedViewTest_View(PersistedViewTest_ID);
GO
现在,让我们尝试再次运行查询,但是这次针对视图:
SELECT pv.PersistedViewTest_ID, pv.TestComputedColumn
FROM dbo.PersistedViewTest_View pv
WHERE pv.TestComputedColumn = CONVERT(INT, 26)
GO
现在,新的执行计划为:
如果要相信新计划,则在该视图上添加视图和聚簇索引之后,统计信息似乎表明执行查询所需的时间现在已加倍。此外,请注意,运行查询后,没有创建新的统计对象来支持新索引,这与表上的查询不同。
查询计划仍然建议创建非聚集索引将对改善查询性能非常有帮助。那么,这是否意味着必须先在视图中添加非聚集索引,然后才能获得所需的性能改进?还有最后一件事可以尝试。修改查询以使用“ WITH NOEXPAND”选项:
SELECT pv.PersistedViewTest_ID, pv.TestComputedColumn
FROM dbo.PersistedViewTest_View pv WITH (NOEXPAND)
WHERE pv.TestComputedColumn = CONVERT(INT, 26)
GO
这将导致以下查询计划:
该执行计划看起来与Max Vernon答案中给出的非聚集索引生成的执行计划非常相似。但是,这是通过减少一个(非聚集)索引和减少一个统计对象来完成的。
事实证明,必须将NOEXPAND选项与SQL Server的快速版本和标准版本一起使用,才能正确使用索引视图。Paul White的精彩文章阐述了使用NOEXPAND选项的好处。他还建议将此选项与企业版一起使用,以确保优化程序使用视图索引提供的唯一性保证。
上面的分析是使用SQL Sever 2014的快速版进行的。我也使用SQL Server 2016的开发人员版进行了尝试。开发版似乎不需要NOEXPAND选项即可获得性能提升,但仍建议使用。
不到5个月前,微软免费提供了开发人员版本。该许可证仅将其用于开发,这意味着该数据库不能在生产环境中使用。因此,如果您一直在尝试测试内存优化表,加密,R等,那么您将不再拥有无许可证的借口。几天前,我已成功将其与SQL Server 2014 Express一起安装在计算机上,没有任何问题。
WHERE (sintMarketID = 2 AND strType = 'CARD' AND strTier1 LIKE 'GG%')
。