SQL Server 更改执行计划 - 第 2 部分

Mat*_*tej 7 sql-server execution-plan sql-server-2014

上一个问题:SQL Server 更改执行计划

我们正在使用 SQL Server 2014 开发人员版。

SQL Server 在相同的查询和相同的数据库和 SQL Server 上更改执行计划(我检查了几次)。

如果我使用 AD 帐户从我的开发计算机连接 Management Studio,则完成查询需要 18 秒(大部分时间)。如果我远程连接到服务器并在 Management Studio 中执行查询,则需要 2 秒才能完成。在我同事的机器上,Management Studio 需要 2 秒,如果他与 MVC 应用程序 (Ado.Net) 连接,则需要 18 秒。

我们做过的事

  • 重新启动 SQL Server
  • DBCC FREEPROCCACHE
  • sp_updatestats
  • 尝试使用不同的用户 AD 和 SQL 用户

执行计划缓慢

执行计划缓慢

快速执行计划

快速执行计划

询问

SET ANSI_NULLS ON
GO

SET ANSI_PADDING ON
GO
SET ANSI_WARNINGS ON
GO
SET ARITHABORT ON
GO
SET CONCAT_NULL_YIELDS_NULL ON
GO
SET NUMERIC_ROUNDABORT OFF
GO
SET QUOTED_IDENTIFIER ON
GO

DECLARE @ccode varchar(500)
DECLARE @PageSize int
DECLARE @PageNumber int
SET @ccode = '%skd%'
SET @PageSize = 20
SET @PageNumber = 1

SELECT DISTINCT CLASSIFICATIONS.ABBREV_TEXT,
            CLASSIFICATIONS.TITLE_TEXT,             
            CLASSIFICATIONS.CFN_UID
    FROM klasje.dbo.CLASSIFICATIONS
    inner join Klasje.dbo.CFN_VERSIONS on CLASSIFICATIONS.CFN_UID = CFN_VERSIONS.CFN_UID
    inner join Klasje.dbo.VERSION_CATEGORY_XREFS on CFN_VERSIONS.CVN_UID = VERSION_CATEGORY_XREFS.CVN_UID
    left outer join Klasje.dbo.VELJAVNOST on CFN_VERSIONS.LIFE_CYCLE_CODE = VELJAVNOST.RV_LOW_VALUE
    WHERE CATEGORY_CODE like @ccode OR DESCRIPTOR_TEXT like @ccode OR DEFINITION_TEXT like @ccode
    ORDER BY ABBREV_TEXT
    OFFSET @PageSize * (@PageNumber - 1) ROWS FETCH NEXT @PageSize ROWS ONLY
Run Code Online (Sandbox Code Playgroud)

gist 上的两个执行计划。

SELECT @@OPTIONS 在两种情况下(慢速和快速)都返回 5496。

Pau*_*ite 11

最可能的解释是您的会话具有不同的设置。SQL Server 具有各种会话设置,这些设置会影响所选的执行计划(以及结果!)

这些设置的值可能取决于您连接到 SQL Server 的方式,因为不同的工具在连接时以不同的方式设置选项,有些(如 SQL Server Management Studio)也允许您覆盖默认值。

例如:

默认选项

上图转载自 Erland Sommarskog 关于此主题的权威文章:

应用程序慢,SSMS 快?了解性能之谜

整件事非常值得一读,但您绝对应该阅读标题为“默认设置”的部分

如果您确保所有连接上的所有设置都具有相同的值,则您应该获得相同的执行计划。

为了最大限度地兼容索引视图等功能,您应该确保您的设置如下:

推荐设置

其中许多设置仅出于向后兼容性而保留。强烈建议您按照上表所示设置它们,或使用自动以正确方式设置它们的工具。

网上书籍参考:

提供计划后更新

慢速计划包括:

CardinalityEstimationModelVersion="70"
Run Code Online (Sandbox Code Playgroud)

...而快速计划说:

CardinalityEstimationModelVersion="120"
Run Code Online (Sandbox Code Playgroud)

所以解释是你们中的一个使用原始基数估计器,另一个使用新的 SQL Server 2014 CE。估计行数的差异足以让新 CE 选择并行执行计划。在原始 CE 下,串行计划的估计成本低于并行性的成本阈值。

至于为什么使用不同的估算器,我猜想您在运行语句时有不同的上下文数据库。一种是数据库兼容级别默认为新CE,另一种是使用原CE。执行查询时您所在的数据库决定了 CE 模型,而不是查询中使用的数据库。

例如,您的登录名可能有不同的默认数据库。如果您USE Klasje;在运行语句之前,两个连接应该使用相同的 CE 模型。

最终更新:事实证明目标数据库确实设置为较旧的兼容级别。使用master作为上下文数据库运行查询会产生更好的计划。请注意,更改为对所有查询使用新 CE 可能会导致回归。在生产中更改数据库兼容性级别之前,您需要测试您的工作负载。