我对任何类型的调优都很陌生,但一直在学习更多。我的一个特定数据库中发现的慢速查询问题之一是许多隐式转换。据我了解,当比较 2 种不相似的列类型时,SQL Server 必须将一种转换为另一种,有优先级列表告诉它如何转换——由于数据类型已转换,它可能不会使用索引正确.. 确定的第一个查询是一个非常基本的查询,我想看看是否有人可以帮助我确定我在执行计划中看到的内容......
基本查询是:
(
@1 TINYINT
,@2 VARCHAR(8000)
,@3 NUMERIC(4, 0)
)
SELECT CONVERT([float], [low] / @3, 0)
FROM [master].[dbo].[spt_values]
WHERE [number] = @1
AND [type] = @2
执行计划显示:
聚簇索引查找的详细信息
spt_vaules.Type 定义为 nchar(3)
Seek Predicates 部分让我感到困惑,它到底在转换哪一部分......我的查询说 [low] 正在从 int 转换为 numeric 但这似乎不是集群索引搜索细节显示的内容,是它?
有没有办法在这个具体的例子中告诉我如果我明确地进行转换会有多少“更好”?我认为我可以在查询中进行“转换”并在变量所在的位置插入一些数字,对吗?
为什么您的输入参数与表的类型不匹配?为什么要保留错误的类型并执行任何强制转换或转换(无论是隐式还是显式)?你为什么要将任何东西转换为
FLOAT
, of all things?解决具体问题:的转换
low
发生在输出中,而不是在查找谓词中(谓词用于查找匹配行和/或消除不匹配行)。除了生成不同的计划并进行比较之外,没有办法让执行计划向您展示不同的计划会有多好。您可以使用此比较来记录如果接口正确会有多好(另外两种方法是保留接口但是(a)在查询中执行显式转换 - 不是列,而是变量或(b) 使用正确类型的局部变量并为它们分配参数值)。所以你可以向他们展示 3 种不同的方法来解决问题,并展示所有 3 种方法都比当前版本更好的证据。
我的建议是以正确的方式修复程序。首先让我们看看您关心的实际类型:
结果:
所以你的存储过程的接口应该是:
varchar 和 nvarchar 之间的隐式转换可能特别糟糕(尤其是在与您相反的情况下 - 参数是 nvarchar 并且列是 varchar),但是当可能的最长字符串时,确实没有理由允许任何类型的 8000 个字符的参数表中是3个字符...