2013-03-12 29 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