Linq to SQL在进行连接时创建额外的子选择
我有一个简单的父子关系,我想用LINQ to SQL加载。 我想与父母同时加载孩子。 生成的SQL做了太多工作。 它试图计数孩子以及加入他们。 我不会更新这些对象。 我不会将孩子添加到父母身上。 我只对阅读感兴趣。 我已将表格简化为最低限度。 实际上我有更多的专栏。 LINQ to SQL正在生成以下SQL
SELECT [t0].[parentId] AS [Id], [t0].[name], [t1].[childId] AS [Id2],
[t1].[parentId], [t1].[name] AS [name2],
( SELECT COUNT(*)
FROM [dbo].[linqchild] AS [t2]
WHERE [t2].[parentId] = [t0].[parentId]
) AS [value]
FROM [dbo].[linqparent] AS [t0]
LEFT OUTER JOIN [dbo].[linqchild] AS [t1] ON [t1].[parentId] = [t0].[parentId]
ORDER BY [t0].[parentId], [t1].[childId]
我不知道为什么SELECT COUNT(*) ...
在那里。 我宁愿它消失。 在生产中,父表和子表都会有数百万行。 额外的查询耗费大量时间。 这似乎是不必要的。 有没有办法让它消失? 我也不确定ORDER BY
来自哪里。
这些类看起来像这样。
[Table(Name = "dbo.linqparent")]
public class LinqParent
{
[Column(Name = "parentId", AutoSync = AutoSync.OnInsert, IsPrimaryKey = true, IsDbGenerated = true, CanBeNull = false)]
public long Id { get; set; }
[ Column( Name = "name", CanBeNull = false ) ]
public string name { get; set; }
[Association(OtherKey = "parentId", ThisKey = "Id", IsForeignKey = true)]
public IEnumerable<LinqChild> Kids { get; set; }
}
[Table(Name = "dbo.linqchild")]
public class LinqChild
{
[Column(Name = "childId", AutoSync = AutoSync.OnInsert, IsPrimaryKey = true, IsDbGenerated = true, CanBeNull = false)]
public long Id { get; set; }
[ Column( Name = "parentId", CanBeNull = false ) ]
public long parentId { get; set; }
[Column(Name = "name", CanBeNull = false)]
public string name { get; set; }
}
我正在使用类似下面的内容进行查询,生产中会有一个where子句和一个匹配的索引。
using (DataContext context = new DataContext(new DatabaseStringFinder().ConnectionString, new AttributeMappingSource()) { ObjectTrackingEnabled = false, DeferredLoadingEnabled = false })
{
var loadOptions = new DataLoadOptions();
loadOptions.LoadWith<LinqParent>(f => f.Kids);
context.LoadOptions = loadOptions;
var table = context.GetTable<LinqParent>();
context.Log = Console.Out;
// do something with table.
}
很不幸的是,不行。 ORM永远不是最高性能的解决方案; 如果您编写自己的SQL(或使用存储过程),您将始终获得更好的性能,但这是取得的折中。
你看到的是ORM的标准做法; 而不是使用多重结果查询(在我看来,这是最有效的方法,但我不是ORM库作者),ORM将整个图形展平成一个查询,并将所需的所有信息带回 - 包括有助于确定哪些数据重复的信息 - 重建图形。
这也是ORDER BY
来源,因为它要求链接的实体位于连续的块中。
正在生成的查询并不是那么低效。 如果你看看估计的执行计划,你会看到count(*)的开销非常小。 order by子句应该由您的主键进行排序,这可能是您的聚簇索引,因此它对性能的影响也应该很小。
在LINQ查询上测试性能时确保一件事是确保context.Log没有被设置。 将其设置为Console.Out将导致巨大的性能下降。
希望这可以帮助。
编辑:
在仔细观察执行计划后,我发现虽然我的Count(*)只是一个聚簇索引扫描,但它仍然是我执行的33%,所以我同意有这个额外的子查询是令人讨厌的,在sql中选择。 如果这真的是性能瓶颈,那么您可能需要考虑创建视图或存储过程以返回结果。
链接地址: http://www.djcxy.com/p/40807.html上一篇: Linq to SQL creating extra sub select when doing join
下一篇: Fetch from foreign key tables with LINQ and LINQ to SQL