【问题标题】:Entity Framework 6.1 converts OR sequence to IN query introducing a huge performance hitEntity Framework 6.1 将 OR 序列转换为 IN 查询,带来巨大的性能损失
【发布时间】:2018-04-15 23:18:32
【问题描述】:

我有一个状态列表 (6) 来查找条目,我的查询如下以使其可缓存并避免重新编译:

from u in db.Users
where u.Status == "Status1" || u.Status == "Status2" || ... u.Status == "Status6"
select u

直到今天它工作得非常好,我发布了一个更新,没有修改查询,也没有更新任何库,它只是一个与查询无关的静态文本更改,但现在但运行时的查询是不同的,并且造成巨大的性能损失:

SELECT u.* FROM USERS u WHERE u.Status in ("Status1", "Status2", ... "Status6")

为什么 EF6.1 开始将我的 OR 查询转换为 IN 查询以及如何防止它并使我以后不会出现这种行为的另一个问题?

【问题讨论】:

  • status = 's1' or status = 's2'status in ('s1', 's2')在SQL Server中没有区别,肯定有其他问题
  • 也许u.* 在第二个查询中?
  • 这是简化查询,原始查询要大得多,我不能在这里发布。它曾经工作 10-15 毫秒,执行需要一秒钟。
  • 我同意 - 没有区别。也许这是一个参数嗅探问题或陈旧的统计数据。
  • 但是是的 - 不同之处在于它可能会使用新计划,因为它是不同的文本 SQL

标签: sql entity-framework tsql entity-framework-6 contains


【解决方案1】:

大概到现在这样:

where u.Status == "Status1" || u.Status == "Status2" || ... u.Status == "Status6"

WHERE OR x OR y OR z 的身份进入数据库。

EF 6.1 可能会尝试优化该查询,因为您的 WHERE OR 子句中只有 Status 列,并将其作为 WHERE IN 发送到数据库。

我认为WHERE IN 优化只是语法糖,因为查询计划是相等的。

据我所知,WHERE ORWHERE IN 在 SQL Server 中没有区别,因为当它被执行时,WHERE IN 会转换为多个 OR(概念上)。

您可以尝试为该列建立索引并重新查看执行计划。

否则问题不是特定于该列或WHERE 子句。

如果您在多个列上有WHERE 子句(有些已编入索引,有些未编入索引),则可能会出现其他问题,并且只有在此处重新查看您的执行计划才能为您提供帮助。

【讨论】:

  • 这是 11 页的 T-SQL 和执行计划,有待学习和查找根本原因。似乎在发布实体框架重新编译查询后,它触发了不同的执行计划,导致了主要的性能问题。我想我无法控制执行计划,所以我需要让我的查询在执行计划、索引使用等方面更具可预测性。
  • 引入更多上下文(仅用于测试目的)的一个想法是使用这 11 页 TSQL 创建一个存储过程,检查执行计划,然后重新编译执行计划并再次检查。也许你会发现一些东西。
  • 是的,已经按照这个计划,比较查询中的执行计划,试图找到瓶颈。
猜你喜欢
  • 1970-01-01
  • 2013-11-04
  • 1970-01-01
  • 2020-05-07
  • 2014-09-17
  • 1970-01-01
  • 2020-07-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多