【发布时间】: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