2015-10-09 3 views
0

У меня есть набор записей приблизительно 1 миллион записей. Я пытаюсь запросить записи, чтобы сообщать месячные цифры.Медленные данные группировки запросов EF по месяцам/годам

Следующий запрос MySQL выполняет примерно 0,3 секунды

SELECT SUM(total), MONTH(create_datetime), YEAR(create_datetime) 
FROM orders GROUP BY MONTH(create_datetime), YEAR(create_datetime) 

Однако я не могу понять выражение лямбда-рамочный объект, который может выполнять любые вблизи как быстрый

Единственное заявление я пришел с этим фактически работает

var monthlySales = db.Orders 
        .Select(c => new 
        { 
         Total = c.Total, 
         CreateDateTime = c.CreateDateTime 
        }) 
        .GroupBy(c => new { c.CreateDateTime.Year, c.CreateDateTime.Month }) 
        .Select(c => new 
        { 
         CreateDateTime = c.FirstOrDefault().CreateDateTime, 
         Total = c.Sum(d => d.Total) 
        }) 
        .OrderBy(c => c.CreateDateTime) 
        .ToList(); 

Но это ужасно медленно.

Как я могу получить этот запрос, чтобы выполнить так быстро, как это делает непосредственно в MySQL

+0

Какова фактическая команда SQL, отправляемая на сервер? Нам нужно понять, является ли скорость проблемой на стороне сервера или на стороне клиента. –

ответ

0

Я наткнулся на эту установку, которая выполняет быстро

  var monthlySales = db.Orders 
       .GroupBy(c => new { Year = c.CreateDateTime.Year, Month = c.CreateDateTime.Month }) 
       .Select(c => new 
       { 
        Month = c.Key.Month, 
        Year = c.Key.Year, 
        Total = c.Sum(d => d.Total) 
       }) 
       .OrderByDescending(a => a.Year) 
       .ThenByDescending(a => a.Month) 
       .ToList(); 
+0

Да, вот как вы должны это делать. Подобно моему ответу, но я использовал LINQ, который, по моему мнению, более читабельен и короче. –

+0

@ RacilHilan, если он переместил 2 строки кода заказа, код почти одинаков по длине. Использование запроса или синтаксиса метода является лишь предпочтительным. Во многих случаях синтаксис запроса короче (но не в этом случае), но во многих случаях мы *** должны использовать синтаксис метода. Для меня синтаксис метода выглядит лучше с точки зрения ООП и свободного синтаксиса, запрос выглядит лучше в терминах синтаксиса типа SQL. –

+0

@KingKing Нет ничего в том, что вы сказали, что я не согласен с :-). Я ясно сказал ***, вот как вы должны это делать ***, но я просто хотел бы отметить, что два ответа похожи, поэтому OP и другие могут выбирать то, что им нравится. Остальное было моим собственным мнением, поэтому я сказал *** Думаю ***. Я лично всегда использую синтаксис запроса, за исключением двух случаев: 1) когда мы должны, как вы сказали. 2) Когда мне нужен только один или два вызова метода по той очевидной причине, что он короче и яснее, чем запрос в этом случае. –

0

Когда вы делаете «.ToList()» в середине запроса (перед выполнением группировки) EF будет эффективно запросить все заказы от базы данных в памяти, а затем группировать в C#. В зависимости от количества данных в вашей таблице это может занять некоторое время, и я думаю, именно поэтому ваш запрос настолько медленный.

Попытка переписать запрос, имеющий только 1 выражение, перечисляет результаты (ToList, ToArray, AsEnumerable)

+0

После удаления исходного .ToList() скорость запроса не изменилась вообще (примерно 1 минута) – mrb398

+0

Вы проверили SQL, который генерируется запросом сейчас? ((ObjectQuery) yorquery) .ToTraceString() На данный момент у меня нет ящика Mysql для проверки, но я думаю, что он должен работать, если вы начинаете с db.Orders.GroupBy(), а затем выбираете из этого. – dlxeon

0

Попробуйте это:

var monthlySales = from c in db.Orders 
        group c by new { y = c.CreateDateTime.Year, m = c.CreateDateTime.Month } into g 
        select new { 
         Total = c.Sum(t => t.Total), 
         Year = g.Key.y, 
         Month = g.Key.m }).ToList(); 
Смежные вопросы