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
步骤没有选择最佳顺序(smallDataSet
先 largeDataSet
)。如果我向生成的 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.
我正在使用 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
步骤没有选择最佳顺序(smallDataSet
先 largeDataSet
)。如果我向生成的 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.