【问题标题】:SQL Server - JOIN isn't using the optimal order in Entity Framework's generated querySQL Server - JOIN 未在实体框架生成的查询中使用最佳顺序
【发布时间】:2015-07-22 11:31:46
【问题描述】:

我正在使用实体框架在我的数据库上执行一个相当复杂的查询。该查询由其他几个IQueryables.Union() 组成。

为了优化所述查询,我​​分解了不同的子查询并单独测试它们以测量性能,并发现其中一个(我们称之为joinRes)比其他的要慢得多。

joinRes 是两个(过滤的)表之间的连接,其中一个表有大量记录,而另一个表只有几条记录。

var smallDataSet = RepositoryForSmallDataSet.Where(smDs => ... );

var joinRes = smallDataSet.Join(largeDataSet, 
                                 smDs => smDs.SomeID, 
                                 bigDs => bigDs.SomeID, 
                                 (smDs, bigDs) => bigDs)
                          .OrderByDescending(bigDs => bigDs.SomeDate);

// ... IQueryable joinRes will be used in some .Union() operations with other IQueryables into a largeQuery IQueryable...

var result = largeQuery.Take(10).ToList();

查看 SQL Server 中的实际执行计划,我可以看到joinRes 子查询中的Nested Loops 步骤没有选择最佳顺序(首先是smallDataSet,然后是largeDataSet)。如果我在生成的 SQL 中添加OPTION (FORCE ORDER) 提示,子查询会快很多。

问题是我似乎找不到通过实体框架添加该提示的方法,只需将复杂查询(请记住 joinRes 是大型复杂查询的一部分)移动到存储过程中即可一个主要的麻烦(这是一个大量动态生成的查询,并且可能需要大量动态 SQL)。

对如何解决这个问题有什么建议吗?

编辑:

Evaldas Buinauskas 的回答让我走上了正轨。 Poor performance was caused by Key Lookup 以及由 TPT 继承机制引起的一堆其他 JOINS(此问题中未提及)。修复了索引(基于 SQL Server 的执行计划)并重构了继承以改用TPH 方法。

【问题讨论】:

  • 看来您应该更新这些表的统计信息。
  • @AlexanderFedorenko,我确实尝试了EXEC sp_updatestats。以及重建索引。没有运气。
  • 实际查询是什么?为什么你认为订单不是最优的?无论如何,EF/LINQ 不能替代 SQL。如果您必须使用 LINQ 进行连接,则说明您使用了错误的实体/关系。从父实体到子实体应该有一个关系。带有“数据集”一词的实体名称是一种非常强烈的气味

标签: sql-server performance entity-framework database-performance


【解决方案1】:

您的索引是否正确?因为Key Lookup 表示您的索引不包含连接条件,或者它正在输出未包含在您的索引中的列。

建议消除它们(查找)。这是very detailed article 解释如何做到这一点。

当您对表进行索引搜索时会发生键查找,但是 您的查询需要不在该索引中的其他列。 这会导致 SQL Server 必须返回并检索那些额外的 列。

【讨论】:

  • 感谢您的意见,我会调查并回复您。
  • 很好看。这不是唯一的原因,但您的输入是提高性能的关键。谢谢。
猜你喜欢
  • 1970-01-01
  • 2012-03-09
  • 1970-01-01
  • 1970-01-01
  • 2014-01-25
  • 1970-01-01
  • 2017-07-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多