我遇到了一些性能问题。我有以下数据库模型。
我希望选择Entity2中Entity1中没有外键的所有条目,换句话说导航属性必须为null。
我已经提出了以下LINQ查询context.Entity2Set.Where(x => x.Entity1 == null);
并且它可以正常运行,但速度很慢。所以我想知道是否有更好(更快)的方式(除了索引之外)来选择条目。
最后,我想从Entity4中选择条目,因此性能是一个问题。
答案 0 :(得分:2)
您正在查询关系中的主体(Entity2
),而不是依赖关系(Entity1
)。这意味着外键位于表Entity1
中,生成的SQL查询不仅仅是对表Entity2
中列值的查询。为了获得所需的结果,SQL查询必须(通过LEFT OUTER JOIN
)加入两个表。
如果是一对多关系,您的查询就像:“获取所有没有订单商品的订单。”仅通过检查Order
表无法实现这一点,因为外键位于表OrderItem
中,并且查询必须连接两个表。实际上,在此示例中,可以通过索引表OrderItem
中的外键列来改进查询的性能。
不幸的是,在您的示例中,您不能通过索引列来改进查询,因为您具有一对一的关系(不是一对多关系)。由于EF的一对一关系始终是共享主键关联,因此表Entity1
中的外键同时是其主键Id
。
这意味着您的外键列已经被索引 - 即通过表Entity1
中的聚簇主键索引。
生成的SQL查询如下:
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[OtherColumn] AS [OtherColumn]
FROM [dbo].[Entity2] AS [Extent1]
LEFT OUTER JOIN [dbo].[Entity1] AS [Extent2] ON [Extent1].[Id] = [Extent2].[Id]
LEFT OUTER JOIN [dbo].[Entity1] AS [Extent3] ON [Extent2].[Id] = [Extent3].[Id]
WHERE [Extent3].[Id] IS NULL
正如您所看到的,这些表由索引的Id
列连接在一起。第二个冗余的LEFT OUTER JOIN
是实体框架SQL生成中的一个缺陷,它对EF< 5.0。我不确定它是否在EF> = 5.0中解决。我不知道它对于查询性能是否真的重要,因为该行通过同一列将表连接到自身,所以我希望SQL查询优化器能够识别它并忽略执行计划中的行。
本质上:您的LINQ查询很好,即使不是通过向列中添加任何其他索引也无法提高性能。
但是,我建议的是找出 真正慢的东西。它确实是SQL查询,还是从LINQ查询到SQL的转换,还是它可能是返回结果集的对象实现等等?我要做的第一步是将生成的SQL查询粘贴到SQL Server Management Studio中,看看性能如何。即使您不更改LINQ查询,也可能有其他机会来提高性能。
答案 1 :(得分:0)
你说过
没有索引
但对于这个问题,这将是一个错误。索引几乎可以立即找到所有空引用。