2011-08-24 54 views
5

这更像是一个技术性的“如何操作”或“最佳方法”问题。C#LINQ和涉及大型数据集的计算

我们目前需要从数据库中检索记录,将它们放入“内存”列表中,然后对数据执行一系列计算,即最大值,平均值和一些更具体的自定义统计数据。

将数据存入“内存中”列表并不成问题,因为我们使用NHibernate作为我们的ORM,它在从数据库检索数据方面表现出色。我正在寻求的建议是我们应该如何最好地对结果数据列表进行计算。

理想情况下,我想为每个统计量MaximumValue(),AverageValueUnder100(),MoreComplicatedStatistic()等等创建一个方法。当然,将所需的变量传递给每个方法并返回结果。这种方法还可以使单元测试变得轻而易举,并为我们提供出色的覆盖。

如果我们为每个计算执行一次LINQ查询,还是应该尽可能多地将每个统计方法的调用合并为尽可能少的LINQ查询,那么会有性能问题吗?例如,将数据列表传递给名为AverageValueBelow100的方法并没有什么意义,然后将整个数据列表传递给另一个方法AverageValueBelow50,只要这些方法可以有效地用一个LINQ查询执行。

如何在不牺牲性能的情况下实现高水平的粒度和分离?

任何建议......这个问题是否足够清楚?

+4

最好的方法是对数据库执行查询,您可以从索引中获益,从而提高性能 –

+0

真的吗?所以不是处理“内存中”,我们最好查询数据库。一些计算相当复杂,所以我不完全确定这将是最好的方法。 – Rowen

+1

大多数数据库都更快 –

回答

1

根据计算的复杂性,最好在数据库中执行此操作。如果它非常复杂,您需要将其作为对象引入并引发开销,那么您可能希望避免对结果集进行多次迭代。你可能要考虑使用Aggregate。如果需要讨论,请参阅http://geekswithblogs.net/malisancube/archive/2009/12/09/demystifying-linq-aggregates.aspx。您将能够单独测试每个聚合,但是(可能)在单个迭代中投射多个聚合。

1

我不同意最好是“在数据库中完成所有工作”。

编写良好的Linq查询将导致对数据库执行良好的SQL查询,这应该是足够好的性能明智的(如果你不打算做dwh的东西)。这假设你正在使用NHibernate的Linq提供程序,而不是Linq的对象。

它看起来不错,你可以很容易地改变它,并保持你的业务逻辑在一个地方。

如果这对于您的需求来说太慢了,您可能会检查创建的SQL代码并调整您的linq查询,试图预编译它们,最后仍然可以返回编写心爱的存储过程并开始在各地传播您的业务逻辑。

会有性能问题吗?是的,你可能会失去几毫秒,但这是否值得你为分离你的逻辑付出代价?

+0

我并不是建议在数据库中这样做。我只是建议不要获取内存中的所有数据,然后执行实际上是Linq的对象查询。 –

0

要回答“我想为每个统计量创建一个方法”的问题,我建议您建立一种统计学类。下面是一些伪代码表达的想法:

class Statistician 
{ 
    public bool MustCalculateFIRSTSTATISTIC { get; set; } // Please rename me! 
    public bool MustCalculateSECONDSTATISTIC { get; set; } // Please rename me! 

    public void ProcessObject(object Object) // Replace object and Rename 
    { 
     if (MustCalculateFIRSTSTATISTIC) 
      CalculateFIRSTSTATISTIC(Object); 

     if (MustCalculateFIRSTSTATISTIC) 
      CalculateSECONDSTATISTIC(Object); 
    } 

    public object GetFIRSTSTATISTIC() // Replace object, Rename 
    { /* ... */ } 
    public object GetSECONDSTATISTIC() // Replace object, Rename 
    { /* ... */ } 

    private void CalculateFIRSTSTATISTIC(object Object) // Replace object 
    { /* ... */ } 
    private void CalculateSECONDSTATISTIC(object Object) // Replace object 
    { /* ... */ } 
} 

如果要我把要做到这一点,我可能会尝试让代表,而不是方法,它一般和使用的集合,但因为我不知道您的上下文,我会留下来的。另外请注意,我只使用了对象类的Object成员,但这仅仅是因为我并不建议您使用DataRows,Entities或其他东西;我会把它留给那些对我更了解这个主题的人们!