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:看看执行计划就能解释。