【问题标题】:Force hint to index from entity framework to SQL Server强制提示从实体框架索引到 SQL Server
【发布时间】:2011-07-06 16:45:28
【问题描述】:

我在 C# 中从实体框架调用 SQL Server 10,并希望在请求中获得查询提示。数据库有索引,在 Management Studio 中运行 SQL 可以正常操作,但是在 Visual Studio 中使用 Entity Framework 从 C# 调用命令时,查询规划器在已有索引时选择全扫描。

我正在创建动态谓词来请求以下形式的数据:

data.attributeText = data.vegaDB.attributeText.AsExpandable().Where(parentPredicate.Compile()).ToList();

其中parentPredicate 是动态生成的,相当于:

(parentID = p1) AND (attributeName = 'name OR ... ')          

生成 SQL Server 查询计划的来源:

SELECT 
[Extent1].[attributeID] AS [attributeID],  
[Extent1].[parentID] AS [parentID],  
[Extent1].[typeID] AS [typeID],  
[Extent1].[attributeName] AS [attributeName],  
[Extent1].[attributeData] AS [attributeData]  
FROM [dbo].[attributeText] AS [Extent1]

因此,将[Extent1] 替换为直接sql 调用使用的索引[IX_parentID],通过一些在初始c# 调用中执行查询提示的额外命令似乎是解决方案。我环顾四周,但还没有成功。知道如何提出问题吗?

你认为这是正确的解决方案吗?

【问题讨论】:

  • 如果查询优化器选择全表扫描,它可能有充分的理由这样做;表可能太小而无所谓,索引可能没有足够的选择性,统计数据可能已经过时......我会调查为什么,而不是直截了当地强制查询提示。 ....
  • 我已经按照stackoverflow.com/questions/117301/… 的建议运行了查询分析器,并且对设置很满意
  • 如果索引对搜索方式的改进不超过30%,sql命令会选择全扫描而不是索引

标签: c# sql-server entity-framework-4 sql-execution-plan hint


【解决方案1】:

尝试更新数据库中相关表的统计信息,如果统计信息已过时,非最佳查询计划可能会用于所有查询。

【讨论】:

    【解决方案2】:

    运行 SQL 跟踪以找出 实际上为此语句生成的 SQL 查询。

    您的谓词或等效项是否真的出现在查询中SQL Server 看到的

    如果确实出现了,那么您需要通过索引调整向导或类似方法运行那个查询。

    如果不是,那是您的问题 - 这意味着 Entity Framework 正在将整个表加载到内存中并应用谓词本身。

    更新我很确定这就是最后发生的事情:AsExpandable() 无法将您的谓词转换为 SQL,因此它正在生成代码以读取整个表,然后应用返回数据的谓词。

    解决方案是停止使用 AsExpandable 并改用 AsQueryable。使用 AsExpandable 的唯一原因是,如果 AsQueryable 不能提供您需要的功能,我认为这里不是这种情况。

    【讨论】:

    • 你是对的,因为 AsExpandable 将表格拉入内存,我的误解。我已更改为 AsQueryable 并且内存使用量要少得多,尽管它仍然没有获取索引。我尝试使用虚拟动态谓词来确保没有编码错误并将查询简化为以下内容: parentPredicate = (p => p.parentID.Equals(100000)); data.attributeText = data.vegaDB.attributeText.AsQueryable().Where(parentPredicate.Compile()).ToList(); SQL 跟踪仍在调用 SELECT [Extent1].[attributeID] AS [attributeID] 等,如上
    • 所以生成的查询中仍然没有“where”子句?
    • Ben,感谢您在这方面的帮助,非常感谢。需要切换到 AsQueryable 并从 LinqKit 切换到 this dynamic predicate system,因为当 EF 使用 .compile() 构建 LinqKit 时使用的 .invoke() 调用似乎实体框架存在问题。因此,当调用被更改时,它的效果很好: data.attributeText = data.vegaDB.attributeText.AsQueryable().Where(parentPredicate).ToList();即删除.Compile()。我不知道这一切背后发生了什么,但它确实有效!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-23
    • 2014-03-02
    • 1970-01-01
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多