Почему это кросс-соединение так медленно в Linq?

Я написал этот кусок Linq для обработки соединения CROSS, как база данных между несколькими списками.

Но по какой-то причине это очень медленно, когда любой из списков идет больше 3000. Я бы подождал 30 секунд? Эти списки могут пойти в очень большие числа.

Этот запрос зацикливается для каждой связи с данными другого списка, поступающими из ColumnDataIndex.

Любой совет?

ОБНОВЛЕНИЕ ** - Данные вставляются в обычные списки, которые составляются заранее из настроенных источников. Это все в памяти на данный момент.

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: возвращает значение столбца в элементе, соответствующее указанному идентификатору столбца.

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;

  }

Обновить:

Закончилось перемещение данных и запроса в базу данных. Это сводится к скорости до количества мс. Могли бы написать оптимизированную зацикленную функцию, но это был самый быстрый выход для меня.

2 ответа

Решение

Вам на самом деле не нужно выполнять перекрестное соединение. Перекрестные соединения по своей сути являются дорогостоящими операциями. Вы не должны делать это, если вам это действительно не нужно. В вашем случае то, что вам действительно нужно, это просто внутреннее соединение. Вы выполняете перекрестное объединение, в результате чего получается множество значений, которые вам вообще не нужны, а затем вы отфильтровываете огромный процент этих значений, чтобы оставить вас с несколькими нужными вам значениями. Если вы только что сделали внутреннее соединение с самого начала, вы бы вычислили только те значения, которые вам нужны. Это избавит вас от необходимости создавать множество строк, которые вам не нужны, просто чтобы их выбросить.

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();

Вы не делаете перекрестное соединение, а выполняете внутреннее соединение с предложением ON, только в вашем случае это предложение ON в предикате where.

Внутреннее соединение обычно выполняется с двумя хэш-наборами / таблицами, поэтому вы можете быстро найти строку в наборе X на основе значения в строке Y.

Итак, ответ Уэстон в порядке, но вам нужно использовать словари / хеш-таблицы, чтобы сделать это действительно быстро. Имейте в виду, что это может быть больше строк на ключ. Для этого вы можете использовать многозначную хэш-таблицу / словарь, например, такой: https://github.com/SolutionsDesign/Algorithmia/blob/master/SD.Tools.Algorithmia/GeneralDataStructures/MultiValueDictionary.cs

Другие вопросы по тегам