【问题标题】:SQL query performance degrades when using parameter使用参数时 SQL 查询性能下降
【发布时间】:2018-10-21 15:45:37
【问题描述】:

这很快:

SELECT * 
FROM [Assignable Assessors] 
WHERE ([Certificate Type ID] = 'TAA')

但这很慢:

DECLARE @__targetLevel_4 AS nvarchar(8);
SET @__targetLevel_4 = 'TAA';

SELECT * 
FROM [Assignable Assessors] 
WHERE ([Certificate Type ID] = @__targetLevel_4)

这怎么可能?

[Assignable Assessor]是一个视图,它使用了包含很多“最新记录的一组选择”。

[Certificate Type ID] 的类型为 nvarchar(8),并且选择中没有显式类型转换。

我正在使用 Azure SQL 数据库。

【问题讨论】:

  • 也可以在第二个语句的末尾使用OPTION(RECOMPILE)
  • WHERE ([Certificate Type ID] = N'TAA') 怎么样(注意 N)。与varchar 值相比,这是参数化查询作为第一个查询的更好表示,并且参数化查询使用 NVarchar。添加 N 也会使值变成 nvarchar。
  • Igor 所说的——两个查询中的字符串类型是不同的。如果该字段是 varchar 而不是 nvarchar (Unicode),则服务器必须 convert 值。如果字段具有不兼容的排序规则,这可能会强制服务器忽略字段上的任何索引。 [Certificate Type ID] 是如何定义的?

标签: sql sql-server tsql azure-sql-database ssms


【解决方案1】:

您看到的是,当您使用硬编码值“TAA”时,能够使用特定值查看统计信息以创建执行计划。相反,您使用的是局部变量(不是参数),因此它不是查看特定行数的统计信息,而是使用平均行数。如果您将相同的代码放入存储过程中,其中您将有一个参数而不是一个局部变量,那么参数嗅探(对参数值进行采样并将其用于统计信息)将产生更准确的计划。

要验证所有这些,请捕获每个查询的执行计划并查看行数。然后将这些与相关列(或索引)的统计信息进行比较。

【讨论】:

    猜你喜欢
    • 2014-02-18
    • 1970-01-01
    • 2020-05-19
    • 2020-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多