首页 > 解决方案 > 参数化 SQL 查询中变量的影响

问题描述

我有一个参数化查询,看起来像(其中 ? 是应用程序参数):

SELECT * FROM tbl WHERE tbl_id = ?

添加这样的变量对性能有何影响:

DECLARE @id INT = ?;
SELECT * FROM tbl WHERE tbl_id = @id

我试图调查自己,但除了查询计划在第一次运行时编译需要稍长一点的时间之外没有运气。

标签: sqlsql-servertsqlsql-execution-plan

解决方案


如果tbl_id是唯一的,则根本没有区别。我试图解释为什么。

SQL Server 通常可以解决具有许多不同执行计划的查询。SQL Server 必须选择一个。它试图在不费力的情况下找到最有效的方法。一旦 SQL Server 选择了一个计划,它通常会缓存它以供以后重用。基数在执行计划的效率中起着关键作用,即tbl给定值为tbl_id? 时有多少行。SQL Server 存储列值频率统计信息以估计基数。

首先,让我们假设tbl_id它不是唯一的并且具有非均匀分布。

在第一种情况下,我们有tbl_id = ?. 让我们弄清楚它的基数。我们需要做的第一件事就是知道参数的值?。是未知的吗?并不真地。第一次执行查询时我们有一个值。SQL Server 采用这个值,它进入存储的统计数据并估计这个特定值的基数,它估计一堆可能的执行计划的成本,考虑到估计的基数,选择最有效的一个并将其缓存以供以后重用。这种方法大部分时间都有效。但是,如果稍后使用具有非常不同基数的其他参数值执行查询,则缓存的执行计划可能非常低效。

在第二种情况下,我们tbl_id = @id@id在查询中声明的变量,它不是查询参数。哪个是价值@id?SQL Server 将其视为未知值。SQL Server 将存储统计数据的平均频率峰值作为未知值的估计基数。然后 SQL Server 做和以前一样的事情:它估计一堆可能的执行计划的成本,考虑到估计的基数,选择最有效的一个并将其缓存以供以后重用。同样,这种方法在大多数情况下都有效。但是,如果您使用基数与平均值非常不同的一个参数值执行查询,则执行计划可能非常低效。

当所有值具有相同的基数时,它们具有平均基数,因此参数和变量之间没有区别。这是唯一值的情况,因此当值唯一时没有区别。


推荐阅读