在视图上创建聚簇索引后查询视图仍然会产生相同的查询计划
Querying a view after creating a clustered index on it still yields the same query plan
我有以下看法
SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
ALTER VIEW web.vGridHotelBooking
WITH SCHEMABINDING
AS
SELECT
HBK_ID,
COF_ID,
COF_CST_ID,
HTL_Name,
COF_Data
FROM
web.HotelBooking
INNER JOIN
web.CustomerOfferBundle ON COF_ID = HBK_COF_ID
INNER JOIN
web.Hotel ON COF_HTL_ID = HTL_ID;
GO
CREATE UNIQUE CLUSTERED INDEX [CLI_vGridHotelBooking__HBK_ID]
ON [web].[vGridHotelBooking] ([HBK_ID]) ON [PRIMARY]
GO
当我执行语句 SELECT * FROM web.vGridHotelBooking
时,我希望看到单个聚簇索引扫描,但我却得到了这个
这与我直接执行 SELECT 语句时得到的计划相同。
我在这里做错了什么?我已经多次使用物化视图,以前没有遇到过这个问题。
编辑 1
运行 带有 WHERE 子句的查询也无济于事。
SELECT COF_ID
FROM web.vGridHotelBooking
WHERE COF_ID = '06A41DB5-8F14-4E6C-9084-3009E0626DAA';
编辑 2
SELECT HBK_ID
FROM web.vGridHotelBooking
WHERE HBK_ID = 1801151518187788
编辑 3
SELECT HBK_ID
FROM web.vGridHotelBooking WITH (INDEX(CLI_vGridHotelBooking__HBK_ID))
WHERE HBK_ID = 1801151518187788;
编辑 4
运行 这次带有 NOEXPAND 的查询产生了正确的计划。
SELECT *
FROM web.vGridHotelBooking WITH (NOEXPAND)
WHERE HBK_ID = 1801151518187788;
那么问题是 - 为什么会这样?我需要担心这个吗?
因为 CustomerOfferBundle
table 中有 aprx 500 000 行,而 Hotel
table aprx 100 000
编辑 5
如评论中所述,您可以使用 WITH (NOEXPAND)
提示强制使用索引视图。
当您这样做时,它表明强制计划的成本估计约为原始计划成本的 10%,因此您可能希望根据成本原因选择此计划。
然而,编译的工作方式是首先扩展视图定义,然后在优化过程的后期可能会或可能不会匹配回索引视图。对于便宜的计划,优化可能会在没有到达那一步的情况下结束。
有关详细信息,请参阅 Paul White's answer here。这也提到
indexed view matching is not available in optimization phase 0
(transaction processing).
事务处理步骤与引用至少 3 个表和嵌套循环连接的查询有关,因此您完全有可能优化到此结束。
如果您增加表的大小(尤其是 HotelBooking
)并且原始计划变得更加昂贵,将花费更多时间进行优化,索引视图可能最终会匹配。
您始终可以使用提示来确定。
我有以下看法
SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
ALTER VIEW web.vGridHotelBooking
WITH SCHEMABINDING
AS
SELECT
HBK_ID,
COF_ID,
COF_CST_ID,
HTL_Name,
COF_Data
FROM
web.HotelBooking
INNER JOIN
web.CustomerOfferBundle ON COF_ID = HBK_COF_ID
INNER JOIN
web.Hotel ON COF_HTL_ID = HTL_ID;
GO
CREATE UNIQUE CLUSTERED INDEX [CLI_vGridHotelBooking__HBK_ID]
ON [web].[vGridHotelBooking] ([HBK_ID]) ON [PRIMARY]
GO
当我执行语句 SELECT * FROM web.vGridHotelBooking
时,我希望看到单个聚簇索引扫描,但我却得到了这个
这与我直接执行 SELECT 语句时得到的计划相同。
我在这里做错了什么?我已经多次使用物化视图,以前没有遇到过这个问题。
编辑 1
运行 带有 WHERE 子句的查询也无济于事。
SELECT COF_ID
FROM web.vGridHotelBooking
WHERE COF_ID = '06A41DB5-8F14-4E6C-9084-3009E0626DAA';
编辑 2
SELECT HBK_ID
FROM web.vGridHotelBooking
WHERE HBK_ID = 1801151518187788
编辑 3
SELECT HBK_ID
FROM web.vGridHotelBooking WITH (INDEX(CLI_vGridHotelBooking__HBK_ID))
WHERE HBK_ID = 1801151518187788;
编辑 4 运行 这次带有 NOEXPAND 的查询产生了正确的计划。
SELECT *
FROM web.vGridHotelBooking WITH (NOEXPAND)
WHERE HBK_ID = 1801151518187788;
那么问题是 - 为什么会这样?我需要担心这个吗?
因为 CustomerOfferBundle
table 中有 aprx 500 000 行,而 Hotel
table aprx 100 000
编辑 5
如评论中所述,您可以使用 WITH (NOEXPAND)
提示强制使用索引视图。
当您这样做时,它表明强制计划的成本估计约为原始计划成本的 10%,因此您可能希望根据成本原因选择此计划。
然而,编译的工作方式是首先扩展视图定义,然后在优化过程的后期可能会或可能不会匹配回索引视图。对于便宜的计划,优化可能会在没有到达那一步的情况下结束。
有关详细信息,请参阅 Paul White's answer here。这也提到
indexed view matching is not available in optimization phase 0 (transaction processing).
事务处理步骤与引用至少 3 个表和嵌套循环连接的查询有关,因此您完全有可能优化到此结束。
如果您增加表的大小(尤其是 HotelBooking
)并且原始计划变得更加昂贵,将花费更多时间进行优化,索引视图可能最终会匹配。
您始终可以使用提示来确定。