使用变量时为什么SQL Server会变慢?

时间:2008-11-24 11:34:37

标签: sql sql-server stored-procedures

我有一个sql查询,在不使用变量时大约一秒运行,如:

WHERE id BETWEEN 5461094 and 5461097

但是当我有:

declare @firstId int
declare @lastId int

set @firstId = 5461094
set @lastId = 5461097

...
    WHERE id BETWEEN @firstId and @lastId

...查询运行速度很慢,仅在几分钟后完成。为什么会这样?我需要使用变量。我可以做任何改进以避免这种性能问题吗?

7 个答案:

答案 0 :(得分:24)

好的,

  1. 您是优化工具,查询计划是一种工具。
  2. 我会给你一个询问,你必须选择车辆。
  3. 图书馆中的所有图书都有序号
  4. 我的查询是去图书馆并获取3到5之间的所有书籍

    你选择一辆正确,快速,便宜,高效且足以携带3本书的自行车。

    新查询。

    进入图书馆,获取@x和@y之间的所有书籍。

    选择车辆。

    继续。

    这就是发生的事情。如果我要求1和Maxvalue之间的书籍,你会选择自卸卡车吗?如果x = 3且y = 5,那就太过分了。 SQL必须在看到数字之前选择计划。

答案 1 :(得分:11)

这是因为当值被硬编码时,它可以查找它对表中数据的the statistics,并找出要运行的最佳查询。查看每个查询的执行计划。使用变量时必须扫描。

如果范围总是很小,您可以使用索引提示来帮助解决这个问题。

答案 2 :(得分:3)

有趣的是,这段代码也很快:

DECLARE @sql VARCHAR(8000)

SET @sql = 'SELECT * FROM table_x WHERE id BETWEEN ' + CAST(@firstId AS VARCHAR) + ' AND ' + CAST(@lastId AS VARCHAR)

EXEC (@sql)

(MSSQL 2000)

答案 3 :(得分:3)

如果这些变量是存储过程的输入变量,则可能会遇到参数嗅探的问题。 http://omnibuzz-sql.blogspot.com/2006/11/parameter-sniffing-stored-procedures.html

答案 4 :(得分:1)

看起来这个查询与存储过程有关,它的执行计划将在第一次执行proc时被编译,然后重新用于后续执行。

编译的计划可能对于第一次真正接近lastid的情况非常糟糕,但是当价值相差很远时,它真的很好。

尝试在存储过程中启用WITH RECOMPILE选项。如果它解决了问题,并且您对每次执行时重新编译的proc感到满意(您将获得性能损失),请将其留在那里。如果您对性能仍然不满意,请考虑重新设计proc,这样就不需要重新编译了。

答案 5 :(得分:0)

索引中的ID(例如主键)?如果没有,请尝试添加一个。

另一件事可能是在第一个(快速)实例中,查询的执行略有不同。我见过的最常见的事情是连接以低效的顺序完成。尝试重新排序连接,或将一些连接转换为子查询。如果您发布更多查询,我们可以进一步提供帮助。

答案 6 :(得分:0)

实际上,答案非常好,我只是在这里写一个解决方法,因为它对我有用:

使用SQL

创建存储过程
WHERE id BETWEEN @firstId and @lastId

然后使用参数@firstId和@lastId调用存储过程,它将加速。我仍然没有100%为什么它正在工作,但它的工作原理。