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