2008-11-24 193 views
15

我有一个运行超快,约为一秒,一个SQL查询不使用变量时,如:为什么SQL Server在使用变量时变慢?

WHERE id BETWEEN 5461094 and 5461097 

但是,当我有:

declare @firstId int 
declare @lastId int 

set @firstId = 5461094 
set @lastId = 5461097 

... 
    WHERE id BETWEEN @firstId and @lastId 

...查询运行非常缓慢,几分钟后才完成。为什么会发生?我需要使用变量。我可以做任何改进以避免这种性能问题吗?

回答

10

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

如果范围总是很小,您可能可以使用索引提示来提供帮助。

+0

在Oracle中,如果范围总是很小,那么一切都会好的。它会根据第一个变量来选择计划。如果它总是很小,你总是很好。 IT是在极端情况下摆动的情况。我认为SS最近添加了一些类似于偷看的东西......也许是'05或'08。 – 2008-11-25 18:36:58

0

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

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

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)

19

OK,

  1. 你是优化和查询计划是车辆。
  2. 我会给你一个查询,你必须选择车辆。
  3. 所有在图书馆的图书上的序列号

我的查询是去图书馆,让我所有的3至5

书你会选择自行车吧,快,便宜,高效和足够大以携带3本书。

新查询。

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

挑车。

继续。

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

+0

已更新的存储过程并添加了“选项重新编译”到最后 – atoms 2015-10-07 10:11:56

1

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

对于firstid与lastid非常接近的情况,其编译计划可能非常糟糕,但是当值相差很远时,它的确很好。

尝试启用存储过程中的WITH RECOMPILE选项。如果它解决了问题,并且您对每次执行过程(您将获得性能提升)重新编译的过程感到满意,那么将它留在那里。如果您对性能仍然不满意,请考虑重新构建proc,以免它需要重新编译。

0

事实上,它是回答得很好,我只是在这里写一个解决方法,因为它的工作对我来说:

与SQL创建一个存储过程

WHERE id BETWEEN @firstId and @lastId 

之后再调用存储过程参数@firstId和@lastId会加快速度。我仍然不是100%,为什么它工作,但它的工作原理。

相关问题