2010-03-10 46 views
5

我正在使用LinqToSQL处理来自SQL Server的数据以将其转储到iSeries服务器中以供进一步处理。 More details on that here速度更快? Struct数组或数据表

我的问题是需要大约1.25分钟来处理这350行数据。我仍然试图破译SQL Server Profiler的结果,但是有一些TON查询正在运行。下面是更详细一点上我在做什么:

using (CarteGraphDataDataContext db = new CarteGraphDataDataContext()) 
{ 
    var vehicles = from a in db.EquipmentMainGenerals 
        join b in db.EquipmentMainConditions on a.wdEquipmentMainGeneralOID equals b.wdEquipmentMainGeneralOID 
        where b.Retired == null 
        orderby a.VehicleId 
        select a; 

    et = new EquipmentTable[vehicles.Count()]; 

    foreach (var vehicle in vehicles) 
    { 
     // Move data to the array 

     // Rates 
     GetVehcileRates(vehicle.wdEquipmentMainGeneralOID); 

     // Build the costs accumulators 
     GetPartsAndOilCosts(vehicle.VehicleId); 
     GetAccidentAndOutRepairCosts(vehicle.wdEquipmentMainGeneralOID); 

     // Last Month's Accumulators 
     et[i].lastMonthActualGasOil = GetFuel(vehicle.wdEquipmentMainGeneralOID) + Convert.ToDecimal(oilCost); 
     et[i].lastMonthActualParts = Convert.ToDecimal(partsCost); 
     et[i].lastMonthActualLabor = GetLabor(vehicle.VehicleId); 
     et[i].lastMonthActualOutRepairs = Convert.ToDecimal(outRepairCosts); 
     et[i].lastMonthActualAccidentCosts = Convert.ToDecimal(accidentCosts); 

     // Move more data to the array 

     i++; 
    } 
} 

get方法看起来都类似:

private void GetPartsAndOilCosts(string vehicleKey) 
{ 
    oilCost = 0; 
    partsCost = 0; 

    using (CarteGraphDataDataContext db = new CarteGraphDataDataContext()) 
    { 
     try 
     { 
     var costs = from a in db.WorkOrders 
        join b in db.MaterialLogs on a.WorkOrderId equals b.WorkOrder 
        join c in db.Materials on b.wdMaterialMainGeneralOID equals c.wdMaterialMainGeneralOID 
        where (monthBeginDate.Date <= a.WOClosedDate && a.WOClosedDate <= monthEndDate.Date) && a.EquipmentID == vehicleKey 
        group b by c.Fuel into d 
        select new 
          { 
           isFuel = d.Key, 
           totalCost = d.Sum(b => b.Cost) 
          }; 

      foreach (var cost in costs) 
      { 
      if (cost.isFuel == 1) 
      { 
       oilCost = (double)cost.totalCost * (1 + OVERHEAD_RATE); 
      } 
      else 
      { 
       partsCost = (double)cost.totalCost * (1 + OVERHEAD_RATE); 
      } 
      } 
     } 
     catch (InvalidOperationException e) 
     { 
      oilCost = 0; 
      partsCost = 0; 
     } 
    } 

    return; 
} 

这里我的想法是削减查询到数据库的数量应加快处理。如果LINQ为每条记录做一个SELECT,也许我需要首先将每条记录加载到内存中。我仍然认为自己是初学C#和OOP的一般人(我主要是在iSeries上进行RPG编程)。所以我猜我正在做一些愚蠢的事情。你能帮我解决我的愚蠢(至少在这个问题上)?

更新:以为我会回来,并更新我发现的内容。看起来好像数据库设计不好。不管LINQ在后台产生什么,它都是非常低效的代码。我并不是说LINQ不好,它只是对这个数据库不利。我转换成一个快速抛在一起的.XSD设置,处理时间从1.25分钟到15秒。一旦我做了适当的重新设计,我只能猜测我会再刮几秒钟。谢谢大家的意见。我会在更好的数据库上再次尝试LINQ。

+0

我自己的2美分数据表在这十年的代码中没有任何地方。 – 2010-03-11 14:02:00

回答

7

还有,我发现在你的代码的几件事情:

  1. 您为每个项目数据库的多次查询中的“变种车”的查询,您可能要重写查询,以便少数据库查询是必要的。
  2. 当您不需要查询实体的所有属性或需要该实体的子实体时,在您的select中使用匿名类型的性能会更好。 LINQ to SQL将分析这个并从数据库中检索更少的数据。这样的选择可能如下所示:select new { a.VehicleId, a.Name }
  3. GetPartsAndOilCosts中的查询可以通过将计算cost.totalCost * (1 + OVERHEAD_RATE)放入LINQ查询中进行优化。这样查询可以完全在数据库中执行,这应该使其更快。
  4. 您正在对var vehicles查询执行Count(),但您只是使用它来确定数组的大小。虽然LINQ to SQL将对其进行非常有效的SELECT count(*)查询,但它需要额外往返数据库。除此之外(取决于你的隔离级别)你开始迭代查询的时间可以被添加。在这种情况下,你的阵列太小,将会抛出ArrayIndexOutOfBoundsException。您可以简单地在查询上使用.ToArray(),或创建一个List<EquipmentTable>并在此上调用.ToArray()。这通常会足够快,特别是当您只有这个集合中的380个项目时,它肯定会比有额外往返数据库(计数)更快。
  5. 正如您可能已经期望的那样,数据库查询的数量是实际的问题。在结构数组或数据表之间切换不会有太大的不同。
  6. 在优化了尽可能多的查询之后,开始分析剩余的查询(使用SQL事件探查器)并使用索引调整向导优化这些查询。它会为你提出一些新的索引,这可以大大加快速度。

的点#1一点点额外的解释。你在做什么这里是一个有点像这样:

你应该尽量做到的是去除query2子查询,因为它是在顶部查询的每一行执行。所以,你可能最终会像这样的东西:

var query = 
    from x in A 
    from y in B 
    where x.Value == y.Value 
    select something; 

foreach (var row in query) 
{ 
} 

当然,这个例子是简单化和在现实生活中它就会变得相当复杂(如你已经注意到)。在你的情况也因为你有多个'子查询'。可能需要一些时间才能做到这一点,尤其是在您对LINQ to SQL缺乏了解的情况下(正如您自己所说的)。

如果你无法弄清楚,你可以在Stackoverflow上再次询问,但请记住将问题解决到最小的可能的事情,因为阅读某人的混乱没有意思(我们没有得到为此付出):-) 祝你好运。

+0

@Steven:对不起,我对#1感到困惑。我不知道该怎么做。我正在研究的所有其他要点。 – 2010-03-10 17:55:03

+0

@Mike:我更新了我的答案。 – Steven 2010-03-10 20:10:37

+0

感谢您的更新。我会研究它。 – 2010-03-10 20:15:21