为啥这是索引扫描而不是索引查找
Posted
技术标签:
【中文标题】为啥这是索引扫描而不是索引查找【英文标题】:why this is an index scan and not an index seek为什么这是索引扫描而不是索引查找 【发布时间】:2017-08-17 09:02:18 【问题描述】:已在 dw_assesment_details
和 dw_assesment_details_id
表上创建聚集索引
/* 6 minutes */
CREATE CLUSTERED INDEX [Ix_DW_ASSESSMENT_DETAILS_qid_QNO_TmpverName]
ON [dbo].[DW_ASSESSMENT_DETAILS_QUESTION_ID]
(
[TEMPLATENAME] ASC,
[TEMPLATEVERSION] ASC,
[QUESTION_NO] ASC
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF,
DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO
/* 9 minutes */
CREATE CLUSTERED INDEX [Ix_DW_ASSESSMENT_DETAILS_QNO_TmpverName]
ON [dbo].[DW_ASSESSMENT_DETAILS]
(
[TEMPLATENAME] ASC,
[TEMPLATEVERSION] ASC,
[QUESTION_NO] ASC
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF,
DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
SELECT
[GETQUESTIONID],
dw.[TEMPLATENAME], dw.[TEMPLATEVERSION],
dw.[QUESTION_NO]
FROM
[QIS_DW].[dbo].[DW_ASSESSMENT_DETAILS] dw
INNER JOIN
[QIS_DW].[dbo].[DW_ASSESSMENT_DETAILS_QUESTION_ID] id ON dw.TEMPLATENAME = id.TEMPLATENAME
AND dw.TEMPLATEVERSION = id.TEMPLATEVERSION
AND dw.QUESTION_NO = id.QUESTION_NO
但是上面的选择查询使用的是索引扫描——而不是索引查找。如何改用索引查找?
性能调优专家有什么建议吗?
【问题讨论】:
您正在读取所有数据,并且两个表具有以相同顺序显示数据的索引。您不想要索引搜索 您可能想阅读RBarry Young's Answer on this question 【参考方案1】:如何改用索引查找?
如果您想尝试超越 SQL Server 优化器,您可以指定 LOOP JOIN
查询提示。我希望MERGE JOIN
的计划在多行时表现更好。
请注意,存储引擎还可能在大型扫描期间执行异步预读,以将数据预取到内存中,以便查询可以使用这些数据,而无需等待从存储中读取。返回几行的搜索不会发生预读。
尝试以下查询,看看您的环境是否属于这种情况。
SET STATISTICS IO ON;
SET STATISTICS TIME ON;
GO
SELECT
[GETQUESTIONID],
dw.[TEMPLATENAME], dw.[TEMPLATEVERSION],
dw.[QUESTION_NO]
FROM
[QIS_DW].[dbo].[DW_ASSESSMENT_DETAILS] dw
INNER JOIN
[QIS_DW].[dbo].[DW_ASSESSMENT_DETAILS_QUESTION_ID] id ON dw.TEMPLATENAME = id.TEMPLATENAME
AND dw.TEMPLATEVERSION = id.TEMPLATEVERSION
AND dw.QUESTION_NO = id.QUESTION_NO;
GO
SELECT
[GETQUESTIONID],
dw.[TEMPLATENAME], dw.[TEMPLATEVERSION],
dw.[QUESTION_NO]
FROM
[QIS_DW].[dbo].[DW_ASSESSMENT_DETAILS] dw
INNER JOIN
[QIS_DW].[dbo].[DW_ASSESSMENT_DETAILS_QUESTION_ID] id ON dw.TEMPLATENAME = id.TEMPLATENAME
AND dw.TEMPLATEVERSION = id.TEMPLATEVERSION
AND dw.QUESTION_NO = id.QUESTION_NO
OPTION(LOOP JOIN);
GO
【讨论】:
【参考方案2】:在 SQL Server 中,聚集或非聚集索引表搜索更改索引扫描,直到我们没有在 Where 子句中添加条件。
Where 子句将使 Index seek 作为执行计划。 如果没有 Where 子句,它充当索引扫描来搜索整个表数据。 这就是为什么索引扫描总是很慢的原因。
【讨论】:
以上是关于为啥这是索引扫描而不是索引查找的主要内容,如果未能解决你的问题,请参考以下文章
技术分享 为啥 SELECT 查询选择全表扫描,而不走索引?