查询是直接比较的快速,但没有与同列索引的表比较,但没有。

查询是直接比较的快速,但没有与同列索引的表比较,但没有。

问题描述:

我有一个相当复杂的查询,如果提供的话,它与@EventId进行直接比较,并且因为它抓取了聚集索引行而快速查询。但是,有时我需要做一组这些事件ID,而第二行需要将近30秒才能运行。我认为它将以相同的方式查找主键。它有这么慢的原因吗?查询是直接比较的快速,但没有与同列索引的表比较,但没有。

DECLARE @EventIds TABLE(Id INT NOT NULL); 

    WHERE 
     (@EventId IS NULL OR (ev.Id = @EventId)) AND 
     (NOT EXISTS(SELECT 1 FROM @EventIds) OR ev.Id IN (SELECT * FROM @EventIds)) 
+0

查看执行计划并告诉我们两个查询之间有什么区别。 –

有没有真正的很好的理由有表达

NOT EXISTS(SELECT 1 FROM @EventIds) OR ev.Id IN (SELECT * FROM @EventIds) 

第一个表达式,即使是真的,不排除第二个表达式的评价,因为SQL Server不快捷布尔表达式。

其次,由于表变量已知由于不正确的统计和行计数而导致错误的执行计划。请参阅此essay on the difference between table variables and temporary tables,主题:基数无栏统计

这可能有助于在查询的结尾处添加以下query hint

OPTION(RECOMPILE); 

这是每次重新编译的计划,但如果你得到可怕的表现小额的编译时不非常重要。

如果您拥有可选筛选器,并且与@EventId一致,那么还建议使用此查询提示。

它也可能有助于在@EventIds表变量上定义Id上的主键。这将允许索引查找而不是表扫描。

+0

我的意思是OPTION(RECOMPILE),而不是WITH(RECOMPILE)(编辑)。 –

+0

我确实把它放在最后,因为某种原因,它加速了并且把它拿出来了,它还是更快。世界发生了什么?它是否节省执行计划缓慢? –

+0

我在这个SP中有相当多的查询参数。我应该像你说的那样使用重新编译吗? –