SQL 服务器 - JOIN 未使用 Entity Framework 生成的查询中的最佳顺序

SQL Server - JOIN isn't using the optimal order in Entity Framework's generated query

我正在使用 Entity Framework 在我的数据库上执行一个相当复杂的查询。查询由 .Union() 和其他几个 IQueryables.

组成

为了优化上述查询,我​​分解了不同的子查询并单独测试它们以衡量性能,发现其中一个(我们称之为 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 服务器中的实际执行计划,我可以看到 joinRes 子查询中的 Nested Loops 步骤没有选择最佳顺序(smallDataSetlargeDataSet)。如果我向生成的 SQL 添加一个 OPTION (FORCE ORDER) 提示,子查询会快得多。

问题是我似乎无法找到一种方法来通过 Entity Framework 添加该提示,而只是简单地移动复杂查询(请记住 joinRes 是一个大型复杂查询的一部分) 到存储过程将是一个主要的麻烦(这是一个高度动态生成的查询,它可能需要大量的动态 SQL)。

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

编辑:

Evaldas Buinauskas 的回答让我走上了正确的轨道。 Poor performance was caused by Key Lookup as well as a bunch of other JOINS caused by a TPT inheritance mechanism (not mentioned in this question). Fixed the indexes (based on SQL Server's execution plan) and refactored inheritance to use a TPH 改为方法。

你的索引对吗?因为 Key Lookup 表示您的索引不包含连接条件或者它输出的列不包含在您的索引中。

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

Key lookups occur when you have an index seek against a table, but your query requires additional columns that are not in that index. This causes SQL Server to have to go back and retrieve those extra columns.