【问题标题】:SQL Server chooses inefficient plan (via EntityFramework)SQL Server 选择低效计划(通过 EntityFramework)
【发布时间】:2014-04-20 13:08:46
【问题描述】:

很抱歉这篇冗长的帖子,没有图片很难描述这个问题。简而言之,SQL 对同一查询使用不同的查询计划(取决于我是否使用参数)。我知道这是参数嗅探的问题,但由于我使用的是实体框架,所以我没有办法为我的查询使用提示。

餐桌设计

这是表格设置的图片(我在这个例子中只使用了几个字段)

示例查询

    SELECT TOP 10 * FROM MarketItems mk
    JOIN ItemAttributes attr ON mk.TypeId == attr.Id
    WHERE attr.Name LIKE '%item_name%' AND Expired = 0
    ORDER BY mk.LastSeen DESC

市场项目表说明:

TypeID 和 LastSeen 都已编入索引。过期是一个位字段。 平均而言,大约有大约 40,000 件物品未过期,大约 400 万件以上已过期(这甚至不重要)。

物品属性表说明:

对于项目属性表,仅索引主键 (Id),大约有 ~20,000 条记录。

问题

当 EF 在查询中使用参数并且查询空数据需要 6 秒以上时会发生这种情况,通常情况下它应该几乎是即时的。即使我在属性表中搜索不存在的名称,完成查询也需要大约 6 秒。似乎它正在遍历所有市场项目,并且每次都在属性表中进行文本查找。

糟糕的执行计划

这是带参数的查询计划(无数据运行需要 6-7 秒)

完整链接:https://puu.sh/8fNKy/2a98367722.png

良好的执行计划

这是没有参数的完全相同的查询(当然,对于任何字符串或项目都会立即运行):

完整链接:https://puu.sh/8fNSH/6c6f7039fe.png

所以,问题是为什么 SQL 会生成如此糟糕的计划,或者我如何强制 EF (6.1) 使用不同的计划或接受查询提示。 我愿意接受有关如何解决此问题的任何其他建议。

谢谢!

【问题讨论】:

  • 您是否尝试过启用强制临时参数化和基准测试?您是否确保您的统计数据是最新的?
  • 是的,我重建了所有索引,并更新了所有统计信息。我现在将研究临时参数化和基准测试
  • 另外:WHERE attr.Name LIKE '%item_name%' 可能会阻止使用任何可用的索引。
  • Name 是 Nvarchar 列吗?
  • 是的,应该不会有什么不同吧?只有 20k 条左右的记录需要搜索

标签: c# sql sql-server entity-framework


【解决方案1】:

很难假设优化器在没有执行计划的完整 XML 以及相关统计信息的情况下生成这个或那个计划的原因。

但是,您还询问了如何强制使用特定计划,对此有一个答案。

使用计划指南告诉优化器该做什么。使用特定查询的计划指南,您可以指定某些优化器提示甚至整个执行计划。如果缓存中有一个好的计划,那么使用计划指南很容易修复它。

这一切都在在线书籍中得到了很好的解释:

http://technet.microsoft.com/en-us/library/ms179880.aspx

您也可以打开强制参数化,但要小心并彻底测试,因为它是数据库范围的设置,会影响每个查询,无论好坏。

【讨论】:

  • 谢谢,我去看看
猜你喜欢
  • 1970-01-01
  • 2013-12-24
  • 2014-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-18
  • 2011-03-22
  • 2020-10-16
相关资源
最近更新 更多