LINQ Group очень медленно - PullRequest
       3

LINQ Group очень медленно

5 голосов
/ 17 августа 2011

Следующий код занимает 5 минут для запуска на 100 000 строк. Это кажется мне безумным. Что я делаю не так?

        var query =
            from foo in fooStuff.AsEnumerable()
            group foo by foo.Field<Int64>("FooID") into g
            select new
            {
                    FooID = g.Key,
                    FooTier = g.Min(foo => foo.Field<int>("Tier"))
            };

Примечание: в моно.

Ответы [ 2 ]

5 голосов
/ 18 августа 2011

Вы материализуете все сущности, когда вызываете AsEnumerable (), поэтому ваша группировка выполняется в памяти.Попробуйте удалить эту часть, чтобы группировка выполнялась на уровне базы данных:

var query =
        from foo in fooStuff
        group foo by foo.FooID into g
        select new
        {
                FooID = g.Key,
                FooTier = g.Min(foo => foo.Tier)
        };
3 голосов
/ 18 августа 2011

Это не прямое сравнение и не для Mono, но у меня есть некоторый код, который делает нечто похожее на 6-мегабайтный XML-файл, который я считал в DataSet, и он имеет 30000 строк и занимает 0,5 секунды, поэтому я не Я думаю, что проблема заключается в самой группе.

Для дальнейшей диагностики я бы предложил

  • Проверка того, сколько времени потребуется для считывания информации в список, т. Е.

    var fooList = fooStuff.AsEnumerable().ToList(); 
    
  • Проверка того, сколько времени потребуется, если вы измените запрос на использование fooList вместо fooStuff

  • Проверка того, сколько времени потребуется, если вы удалите FooTier = g.Min (foo => foo.Tier) из выбранного

  • Отделите отражение .Field <> от группы и время каждого раздела, т.е. сначала прочитайте информацию из таблицы данных в список, например,

    var list2 =
    (from foo in fooStuff.AsEnumerable()
    select new { 
        FooID = foo.Field<Int64>("FooID") 
        Tier  = foo.Field<int>("Tier")
    }).ToList();
    

    Затем вы можете запросить этот список

    var query =
    from foo in list2
    group foo by foo.FooID into g
    select new
    {
            FooID = g.Key,
            FooTier = g.Min(foo => foo.Tier)
    };
    var results = query.ToList();
    

Если этот запрос медленный, то можно предположить, что что-то не так с реализацией mono GroupBy. Вы можете убедиться в этом, используя что-то вроде этого

    public static Dictionary<TKey, List<TSrc>> TestGroupBy<TSrc, TKey>
     (this IEnumerable<TSrc> src, Func<TSrc,TKey> groupFunc)
    {
        var dict= new Dictionary<TKey, List<TSrc>>();

        foreach (TSrc s in src)
        {
            TKey key = groupFunc(s);
            List<TSrc> list ;

            if (!dict.TryGetValue(key, out list))
            {
                list = new List<TSrc>();
                dict.Add(key, list);
            }       
            list.Add(s);        
            }

        return dict;
}

и использовать его

  var results = list2.TestGroupBy(r=>r.FooID)
      .Select(r=>  new { FooID = r.Key, FooTier = r.Value.Min(r1=>r1.Tier)} );

Обратите внимание, что это не означает замену groupby и не справляется с нулевыми ключами, но должно быть достаточно, чтобы определить, является ли их проблема с groupby (при условии, что моно для реализации Dictionary и List в порядке).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...