Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL查询可以快速处理“中的19项”;在;子句-20的速度慢得多。为什么?_Sql_Sql Server 2005_Optimization - Fatal编程技术网

SQL查询可以快速处理“中的19项”;在;子句-20的速度慢得多。为什么?

SQL查询可以快速处理“中的19项”;在;子句-20的速度慢得多。为什么?,sql,sql-server-2005,optimization,Sql,Sql Server 2005,Optimization,我有一个查询,其中包括: ... AND Record.RecordID IN (1,2,3,10,11,12,13,16,17,18,26,27,28,557,31,32,33,36,37,93) AND ... 问题似乎是,如果该列表中有20项或更多项,则执行查询需要超过25秒。如果少于20,则立即执行。有没有关于如何优化的想法?这看起来很肮脏而且没有必要,但是你试过: (Record.RecordID IN (--19 items--) OR Record.RecordID = 20th

我有一个查询,其中包括:

... AND Record.RecordID IN (1,2,3,10,11,12,13,16,17,18,26,27,28,557,31,32,33,36,37,93) AND ...

问题似乎是,如果该列表中有20项或更多项,则执行查询需要超过25秒。如果少于20,则立即执行。有没有关于如何优化的想法?

这看起来很肮脏而且没有必要,但是你试过:

(Record.RecordID IN (--19 items--) OR Record.RecordID = 20th_item) AND

我不知道为什么将第20项添加到组中的
会将其推到边缘。

要做的一件事是查看优化器计划(如果可以的话),看看当使用20项或更少项时与使用>20项时,计划有何不同。例如,在Oracle中,可以使用explain plan命令查看此输出

以下是有关如何在Oracle中使用explain plan的一些信息:

其他的事情要考虑的是你是否有一个索引。这可能是因为,一旦您超过某个阈值(在您的情况下大于20项),优化器就会决定使用完整表扫描比使用索引更好

有时,对于某些数据库,如果确实可以提高性能,您可以使用优化器提示说服优化器使用索引

以下是指向优化器提示的链接,您可以阅读:


我的答案是以Oracle为中心,但同样的原则应该适用于大多数数据库。

将RecordID放在临时表中,并使用
内部联接对其进行筛选。对于SQL Server,这看起来像:

declare @RecordIds table (int RecordID)
insert into @RecordIds values (1)
insert into @RecordIds values (2)
...
insert into @RecordIds values (93)

select r.*
from Records r
inner join @RecordIds ri on ri.RecordID = r.RecordID
对于MySQL来说,“in列表中的值的数量只受值的限制。”这似乎不太可能是问题所在,但这是一个值得关注的地方


在任何情况下,将
In()
值存储在临时表中,并将查询与临时表连接起来,都可以解决整个问题。

第20项恰好将此特定查询成本估算的平衡从一个计划转移到另一个计划。对于20个项目,您可能会得到一个完整的表格扫描。IN只是OR的语法糖。。或或或或者是好的查询计划的敌人。按照Andomar的建议,使用连接

更新


如果您不使用IN语法,还可以使用,并确保查询保持在最佳计划上。IN语法强制您在每次执行时更改查询,因此您不能使用查询计划提示。

CLR表值函数将是根据提供的参数创建表的另一种方法-有关更多信息,请参阅添加第20项时,优化器似乎会生成不同的执行计划。执行计划是根据统计数据制定的。搜索条件会影响预期的结果行。当您在条件列表中添加更多项时,预期返回的行将发生变化,优化器可能会生成新的执行计划

检查两个查询的执行计划(CTRL-L)。这是了解为什么列表中的项目超过20项会花费更多时间的唯一方法

在检查执行计划之前,请更新表的统计信息:

UPDATE STATISTICS records
如果你能等的话

UPDATE STATISTICS records WITH FULLSCAN

第二个将花费更多的时间,但你会有更一致的统计数据。

+ 1:查看Oracle的流水线函数:好的建议,但是由于一些限制,我真的希望在没有临时表的情况下实现这一点…@ RabeDutad:那么考虑CLR表值函数:RelDID是主键吗?如果没有,上面有索引吗?查询分析器对此有何评论?让我澄清一下-查询包含19个以上的项,只是运行速度非常慢。似乎它可能是优化器。如果查询时间比您预期的要长并且没有失败,您应该编辑帖子的标题。
col1 IN(a,b,c)
col1=a或col1=b或col1=c
,所以我怀疑这是否有助于MSSQL:看看执行计划就能解释。