在两个索引表上使用组和连接进行单独 LINQ2SQL 选择与一个组合选择的性能

Posted

技术标签:

【中文标题】在两个索引表上使用组和连接进行单独 LINQ2SQL 选择与一个组合选择的性能【英文标题】:Performance of separate LINQ2SQL selects with group and join on two indexed tables vs. one combined select 【发布时间】:2020-02-06 16:10:44 【问题描述】:

我需要从按 ID 分组的表 (tab_activities) 中检索记录,只检索按日期确定的每个组的最新记录。 在这些最新记录中,我只需要那些尚未设置特定属性(已完成)的记录。 最后,我必须交叉检查是否有任何活动也注册在黑名单(tab_flaggedActivities)中,然后对所有未完成且未标记的活动进行处理。

两个表的 id 都有索引。 很明显,id 不是主键。

我不确定我正在做的是否是设置此选择的最佳方式。 将这些单独的选择组合在一个选择中会更好吗?如果是,我该怎么做?

// Retrieve only the latest activity entry of each known activity-ID
var latestActivityRecords = from activity in dc.tab_activities
                            where activity.dateRegistered > DateTime.Now.AddDays(-MaxAge)
                            group activity by activity.id
                            into groups
                            select groups.OrderByDescending(p => p.dateRegistered).First();

// Filter activities that are not finished
var unfinishedActivityRecords = from activity in latestActivityRecords
                                where !activity.finished
                                select activity;

// Check if any of those are in blacklist (different table)
var flaggedActivityRecords = from activity in unfinishedActivityRecords
                             join flaggedActivity in dc.tab_flaggedActivities 
                             on activity.id equals flaggedActivity.id
                             select activity;

if (unfinishedActivities != null)

    // Do something with all unfinished / unflagged activities 
    foreach (var activityRecord in unfinishedActivityRecords)
    
        if (!flaggedActivityRecords.Any(p => p.id == activityRecord.id))
        
            DoSomething(activityRecord);
        
    

【问题讨论】:

您所做的确实将查询组合成一个查询,然后再发送到数据库。检查latestActivityRecords & unfinishedActivityRecords 的类型。由于您没有执行任何操作来执行查询,因此执行将推迟到 foreachif 中的迭代以及 Any 测试。但是,由于Any 测试处于循环中,您应该在分配中执行一次flaggedActivityRecords,方法是添加.ToList(),或者根据大小,可能是.Select(a => a.id).ToHashSet()(在这种情况下,您不妨执行unfinishedActivityRecords). 什么是unfinishedActivities 【参考方案1】:

如果您的意思是将if Any 测试与查询结合起来,您可以颠倒最后一个查询的含义并循环遍历结果,在数据库服务器上执行过滤:

var unflaggedActivityRecords = from activity in unfinishedActivityRecords
                               where !dc.tab_flaggedActivities.Select(fa => fa.id).Contains(activity.id)
                               select activity;

if (unfinishedActivities != null) 
    // Do something with all unfinished / unflagged activities 
    foreach (var activityRecord in unflaggedActivityRecords) 
        DoSomething(activityRecord);
    

【讨论】:

以上是关于在两个索引表上使用组和连接进行单独 LINQ2SQL 选择与一个组合选择的性能的主要内容,如果未能解决你的问题,请参考以下文章

根据两个不同表上的两列对完全连接进行排序

连接表上的索引

如何在内部连接表上强制索引?

使用范围标准对连接表进行 MySQL 优化

GeoServer Image Mosaics:PostGIS 索引表上的查询超过最大连接限制

Oracle查询转换之连接谓词推入