我正在使用Entity Framework在我的数据库上执行相当复杂的查询。该查询包含其他几个.Union()
的{{1}}。
为了优化所述查询,我已经分解了不同的子查询并单独测试它们以测量性能,并发现其中一个(让我们称之为IQueryables
)比其他
joinRes
是两个(已过滤)表之间的连接,其中一个表具有大量记录,而另一个表只有几个。
joinRes
查看SQL Server中的实际执行计划,我可以看到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();
子查询中的Nested Loops
步骤没有选择最佳顺序(joinRes
首先smallDataSet
}})。如果我向生成的SQL添加largeDataSet
提示,则子查询要快得多。
问题是我似乎找不到通过Entity Framework添加该提示的方法,只需将复杂查询(请记住OPTION (FORCE ORDER)
是大型复杂查询的一部分)移动到存储过程中将是一个主要的麻烦(它是一个动态生成的大量查询,它可能需要大量的动态SQL)。
有关如何解决此问题的任何建议?
Evaldas Buinauskas用他的回答让我走上正轨。 Poor performance was caused by Key Lookup
以及由TPT继承机制引起的一堆其他JOINS(本问题中未提及)。修复了索引(基于SQL Server的执行计划)和重构的继承,以改为使用TPH方法。
答案 0 :(得分:2)
你的索引是对的吗?由于Key Lookup
表示您的索引不包含加入条件,或者它输出了未包含在索引中的列。
建议消除它们(查找)。这是very detailed article解释如何执行此操作。
当您对表进行索引查找时会发生键查找,但是 您的查询需要不在该索引中的其他列。 这会导致SQL Server必须返回并检索这些额外的内容 列。