SQL Server选择低效的计划(通过EntityFramework)

时间:2014-04-20 04:21:28

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

抱歉这篇冗长的帖子,有点难以描述没有图片的问题。简单地说,SQL对同一个查询使用不同的查询计划(取决于我是否使用参数)。我理解这是参数嗅探的问题,但是当我使用实体框架时,我没有办法为我的查询使用提示。

表格设计

下面是表格设置的图片(本例中我只使用了几个字段)

database

示例查询

    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个项目未过期,且大约4个月到期(这不应该是重要的)。

项目属性表格描述:

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

问题

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

糟糕的执行计划

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

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

bad_plan

良好执行计划

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

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

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

谢谢!

1 个答案:

答案 0 :(得分:3)

如果没有执行计划的完整XML以及相关统计数据,优化器为什么会产生这个或那个计划,这很难做出任何假设。

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

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

这在网上书籍中得到了很好的解释:

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

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