小编典典

为什么sql存储过程中的'泪N'查询标签如此昂贵?

sql

如何改善绩效问题?我有一个’IN’的SQL查询,我想’IN’造成了一些代价高昂的性能问题。但是我需要索引我的SQL查询吗?

我的SQL查询:

SELECT [p].[ReferencedxxxId]  
FROM [Common].[xxxReference] AS [p]  
WHERE ([p].[IsDeleted] = 0)  
  AND (([p].[ReferencedxyzType] = @__refxyzType_0)
  AND [p].[ReferencedxxxId] IN ('42342','ffsdfd','5345345345'))

我的解决方案:(但我需要您的帮助以更好地建议)哪个是正确的聚簇索引或非聚簇索引?

USE [xxx]
GO
CREATE NONCLUSTERED INDEX IX_NonClusteredIndexDemo_xxxId
ON [Common].[xxxReference](xxxId)
INCLUDE ([ID],[ReferencedxxxId])
WITH (DROP_EXISTING=ON, ONLINE=ON, FILLFACTOR=90)
GO

第二:

CREATE INDEX xxxReference_ReferencedxxxId_index
ON [Common].[xxxReference]  (ReferencedxxxId)[/code]

谁是正确的,或者您有更好的解决方案?


阅读 187

收藏
2021-04-15

共1个答案

小编典典

几件事情:

  1. 如果IN中有SELECT语句,则应避免使用该语句,而应将其替换为EXISTS子句。但是在上面的示例中,这无关紧要,因为您在IN中具有直接值。

使用EXISTS和NOT EXISTS代替IN和NOT IN可以帮助SQL Server不必为IN / NOT
IN内的每个值扫描列的每个值,并且一旦找到匹配项或不匹配项,就可以使搜索短路。

  1. 避免隐式转换。由于许多原因,它们会降低性能,其中包括:i> SQL Server无法在索引上找到适当的统计信息,因此无法利用索引,而宁愿使用表中可用的聚集索引(可能无法涵盖您的查询),ii>在存储引擎查询的内存分配阶段未分配适当的必需RAM,iii>基数估计变得错误,因为SQL Server无法获得该列计算值的统计信息,而可能具有该列的统计信息柱子。

如果您查看上面发布的执行计划,则在“选择”中将看到一个黄色标记。如果将鼠标悬停在它上面,将看到一个/多个警告消息。如果您的警告与隐式转换有关,请在比较期间尝试使用正确的数据类型。

例如。“ [ReferencedxxxId]”列的数据类型是什么?如果不是NVARCHAR而是VARCHAR,那么我建议:

  1. 将IN内的值设置为VARCHAR(当前将其设置为NVARCHAR)。这样,您仍然可以充分利用在[ReferencedxxxId]列上创建的行存储索引。

  2. 如果必须在IN子句中具有NVARCHAR值,则应该:

    • 转换/投射IN子句中的[ReferencedxxxId]列。这将摆脱隐式转换,但是您将不再能够充分利用[ReferencedxxxId]列上的行存储索引。

+

* 而是在覆盖查询中使用的列的表上创建集群/非集群列存储索引。这将大大提高SELECT查询的性能。
  1. 如果您决定通过更正IN中的值来选择使用行存储索引的方法,则需要确保创建一个覆盖查询的聚簇/非聚簇索引。意味着索引覆盖了您要在其上进行搜索的列([ReferencedxxxId],[ReferencedxxxType],[IsDeleted]),然后包括了INCLUDE子句下的SELECT语句中使用的列(如果它是非聚集索引)

  2. 另外,在创建复合行存储索引时,请尝试从左到右保持索引内基数从高到低的顺序,以充分利用该索引。

2021-04-15