2013-03-12 72 views
12

我写了这一块的LINQ的处理做了交叉联接一样将多个列表之间的数据库。为什么这个Cross在Linq加入这么慢?

但由于某种原因,这是非常缓慢的,当任何名单中去比3000更我会等待30秒?这些列表可能会非常多。

该查询循环与来自的其他列表数据的每个关系ColumnDataIndex

什么建议吗?

UPDATE ** - 将数据插入正常列表中,这些列表是从配置的源手动构建的。这一切都在记忆中。

RunningResult[parameter.Uid] = (from source_row in RunningResult[parameter.Uid] 
          from target_row in ColumnDataIndex[dest_key] 
          where GetColumnFromUID(source_row, rel.SourceColumn) == GetColumnFromUID(target_row, rel.TargetColumn) 
          select new Row() 
          { 
           Columns = MergeColumns(source_row.Columns, target_row.Columns) 

          }).ToList(); 

的2个额外的功能:

MergeColumns:从2项注意到列和它们合并成一个单一的阵列。

public static Columnn[] MergeColumns(Column[] source_columns, Column[] target_columns) 
{ 
     Provider.Data.BucketColumn[] new_column = new Provider.Data.BucketColumn[source_columns.Length + target_columns.Length]; 
     source_columns.CopyTo(new_column, 0); 
     target_columns.CopyTo(new_column, source_columns.Length); 
     return new_column; 
    } 

GetColumnFromUID:返回匹配给定的列UID的项目中列的值。

private static String GetColumnFromUID(Row row, String column_uid) 
    { 
     if (row != null) 
     { 
      var dest_col = row.Columns.FirstOrDefault(col => col.ColumnUid == column_uid); 
      return dest_col == null ? "" + row.RowId : dest_col.Value.ToString().ToLower(); 
     } 
     else return String.Empty; 

    } 

更新:

截止了移动数据和查询数据库。这减少到几毫秒的速度。可以写一个优化的循环函数,但这对我来说是最快的出路。

+0

你在哪里定义你的数据源,内部或外部循环。如果在外面,他们是可查询的来源或列表。 – 2013-03-12 13:58:21

+0

我在循环之外构建它们见上面 – 2013-03-12 14:00:09

+11

我的建议:**运行一个探查器**其他任何事情都是猜测。 – 2013-03-12 15:42:19

回答

4

你实际上并不需要执行交叉连接。 交叉连接本质上是昂贵的操作。除非你真的需要,否则你不应该那样做。在你的情况下,你真正需要的只是一个内部连接。您要执行交叉联接这导致大量的,你并不需要在所有的价值,然后你过滤掉这些值的很大比例留给你,你需要的少数。如果你从一开始就做了一个内部连接,你只会计算你需要的值。这将使您无需创建大量不需要的行就可以将它们扔掉。

LINQ都有自己的内部联接操作,Join,所以你甚至不需要写自己:

RunningResult[parameter.Uid] = (from source_row in RunningResult[parameter.Uid] 
           join target_row in ColumnDataIndex[dest_key] 
           on GetColumnFromUID(source_row, rel.SourceColumn) equals 
            GetColumnFromUID(target_row, rel.TargetColumn) 
           select new Row() 
           { 
            Columns = MergeColumns(source_row.Columns, target_row.Columns) 

           }).ToList(); 
+0

已将此查询结束移动到数据库,但此测试在我测试时加快了查询速度。 – 2013-03-14 13:12:05

0

你不是做一个交叉连接,而是与ON子句内连接,只有在你的情况,在那里谓词ON子句。

内连接通常与两个散套/表上完成,这样就可以快速找到基于行Y的值在集合X行

所以,“韦斯顿的答案是确定的,但你需要使用字典/哈希表来使它真的很快。请注意,它可能是每个键有更多行。你可以使用这样一个多值散列表/字典: https://github.com/SolutionsDesign/Algorithmia/blob/master/SD.Tools.Algorithmia/GeneralDataStructures/MultiValueDictionary.cs

+1

他实际上正在交叉加入。他只需*做内部连接,就像他的例子一样,做一个内部连接会大大提高性能。他为了获得与内连接相同的结果而进行交叉连接的事实是性能问题的原因。请注意,LINQ有一个'join'运算符,他可以用来执行内部连接;他不需要创建自己的哈希表来完成它(尽管他当然可以)。 – Servy 2013-03-12 17:36:51

+0

我只是看了这个例子,没有更多。这个例子是这样的:SELECT ... FROM X,Y WHERE X.field = Y.field;一样。 from ... from子句确实意味着交叉连接,但where子句在语义上不是交叉连接。或者更好:他使用from ... from构造的查询对于他想做的事情并不是最佳的。我知道Linq有一个连接操作符,相信我;) – 2013-03-12 22:22:03

+0

事实上,他使用SelectMany后跟一个Where表示他确实正在进行交叉连接。这就是SelectMany *的定义,它是'From X from Y ...'映射到的内容。他正在进行交叉连接,然后将结果过滤为内部连接的结果。这比从头做一次加入花费的时间要多得多,因为您避免了大量不必要的开销。 – Servy 2013-03-13 03:48:13