Linq加入Timstamp订购的三张桌子

时间:2015-10-30 10:07:20

标签: c# linq sql-server-2012 entity-framework-5

我有三张桌子:

Sites:
Id
Timezone (string)
SiteName

Vehicles:
Id
SiteId
Name

Positions:
Id
TimestampLocal (DateTimeOffset)
VehicleId
Data1
Data2
...
Data50

单个车辆有多个位置。位置表非常大(100多万个记录) 我需要获得每辆车的最后位置(通过时间戳,因为他们可以发送旧数据)及其时区,以便我可以根据时区进行进一步的数据处理。像 {PositionId,VehicleId,Timezone,Data1}

之类的东西

我尝试过:

var result = 
from ot in entities.Positions
join v in entities.Vehicles on ot.VehicleId equals v.Id
join s in entities.Sites on v.SiteId equals s.Id
group ot by ot.VehicleId into grp
select grp.OrderByDescending(g=>g.TimestampLocal).FirstOrDefault();

然后我用:

处理数据
foreach (var rr in result){... update Data1 field ...    }

这会获得最后的值,但它会将所有字段都放在Positions(很多数据)中,而不是Timezone。此外,foreach部分非常占用CPU(因为它可能带来数据),因为它可以获得100%的CPU几秒钟。)

如何在Linq中完成...并且对于数据库及其传输是否轻量级?

1 个答案:

答案 0 :(得分:0)

查看以下内容与您完成的行相同,但结果包含投影的Sites Timezone列,投影在加入本身

var result =
S.Join(V,s1=>s1.Id,v1=>v1.SiteId,(s1,v1)=>new {v1.Id,s1.Timezone})
 .Join(P,v1=>v1.Id,p1=>p1.VehicleId,(v1,p1)=>new {p1,v1.Timezone})
 .GroupBy(g=>g.p1.VehicleId)
 .Select(x=>x.OrderByDescending(y=>y.p1.TimestampLocal).FirstOrDefault())
 .Select(y=>new {y.p1,y.Timezone});

以下是与您提出的问题相关的要点:

  1. 要减少提取的列数,因为您可能不需要所有位置列,需要执行以下操作:

    • 在这一行 - Join(P,v1=>v1.Id,p1=>p1.VehicleId,(v1,p1)=>new {p1,v1.Timezone}) 投影字段,这是Join的结果,如:

      new {p1.Id,p1.TimestampLocal,p1.VehicleId,p1.Data1,p1...,v1.Timezone}
      

      仅提供投影字段,但GroupBy将更改为GroupBy(g=>g.VehicleId)

  2. 相同的其他选项是更改GroupBy投影,如下所示,而不是Join语句

    GroupBy(g=>g.p1.VehicleId, 
    g=>new {g.p1.Id,g.p1.TimestampLocal,g.p1.VehicleId,g.p1.Data1,g.p1...,g.Timezone})
    
  3. 现在剩下的部分流程是CPU密集型并且使用100%CPU,可以进行以下优化:

    • 每个foreach循环迭代是否进行网络Update调用,然后它必然会使它成为一个网络密集型进程,因此速度慢,最好是在内存中进行所有必要的更改然后如果您有数百万条记录
    • ,一次性更新数据库仍将是密集型的
  4. 即使为百万条记录做同样的事情也不是一个好主意,因为这将是一个相当网络和CPU密集型,因此使它变慢,你的选择将是:

    • 将内存分成较小的组件,因为我不确定是否需要一次更新百万条记录,所以要进行多个较小的更新,这些更新由用户一个接一个地执行,但是对系统资源的负担要小得多。

    • 在内存中放入较小的数据集,使用参数在数据库级别进行过滤,并在内存中传递必要的数据以进行更新。

    • 使用上面Linq中显示的投影,只带来所需的列,这将减少整体数据内存占用,必然会产生影响。

    • 如果逻辑是各种更新是互斥的,那么在线程安全结构中使用Parallel API来完成它们,这将确保所有内核的高效和快速的CPU利用率,因此速度更快,尽管它会飙升到100%的CPU但是非并行执行的一小部分

    除此之外,还提供了具体细节,以帮助您了解更多详情,这些是基本建议,解决此类优化问题没有黄金法则