Я абсолютно не знаком с LINQ.
У меня есть SQL GroupBy
который работает всего за несколько миллисекунд. Но когда я пытаюсь добиться того же, что и через LINQ, это просто ужасно медленно. То, что я пытаюсь достичь, - это получить среднюю месячную продолжительность обновления базы данных ceratin.
В SQL =>
select SUBSTRING(yyyyMMdd, 0,7),
AVG (duration)
from (select (CONVERT(CHAR(8), mmud.logDateTime, 112)) as yyyyMMdd,
DateDIFF(ms, min(mmud.logDateTime), max(mmud.logDateTime)) as duration
from mydb.mydbo.updateData mmud
left
join mydb.mydbo.updateDataKeyValue mmudkv
on mmud.updateDataid = mmudkv.updateDataId
left
join mydb.mydbo.updateDataDetailKey mmuddk
on mmudkv.updateDataDetailKeyid = mmuddk.Id
where dbname = 'MY_NEW_DB'
and mmudkv.value in ('start', 'finish')
group
by (CONVERT(CHAR(8), mmud.logDateTime, 112))
) as resultSet
group
by substring(yyyyMMdd, 0,7)
order
by substring(yyyyMMdd, 0,7)
в LINQ => Сначала я беру запись из таблицы, которая связывает информацию с именем базы данных и UpdateData, а затем выполняет фильтрацию и группировку по соответствующей информации.
entry.updatedata.Where(
ue => ue.updatedataKeyValue.Any(
uedkv =>
uedkv.Value.ToLower() == "starting update" ||
uedkv.Value.ToLower() == "client release"))
.Select(
ue =>
new
{
logDateTimeyyyyMMdd = ue.logDateTime.Date,
logDateTime = ue.logDateTime
})
.GroupBy(
updateDataDetail => updateDataDetail.logDateTimeyyyyMMdd)
.Select(
groupedupdatedata => new
{
UpdateDateyyyyMM = groupedupdatedata.Key.ToString("yyyyMMdd"),
Duration =
(groupedupdatedata.Max(groupMember => groupMember.logDateTime) -
groupedupdatedata.Min(groupMember => groupMember.logDateTime)
)
.TotalMilliseconds
}
).
ToList();
var updatedataMonthlyDurations =
updatedataInDateRangeWithDescriptions.GroupBy(ue => ue.UpdateDateyyyyMM.Substring(0,6))
.Select(
group =>
new updatedataMonthlyAverageDuration
{
DbName = entry.DbName,
UpdateDateyyyyMM = group.Key.Substring(0,6),
Duration =
group.Average(
gmember =>
(gmember.Duration))
}
).ToList();
Я знаю, что GroupBy в LINQ не совпадает с GroupBy в T-SQL, но не уверен, что происходит за кулисами. Может ли кто-нибудь объяснить разницу и что происходит в памяти, когда я запускаю версию LINQ? После того, как я сделал.ToList() после того, как первые вещи GroupBy стали немного быстрее. Но даже тогда этот способ поиска средней продолжительности очень медленный. Какая была бы лучшая альтернатива и есть способы улучшить медленную инструкцию LINQ с помощью Visual Studio 2012?
Ваш запрос linq выполняет большую часть своей работы в linq-to-objects
. Вы должны создать linq-to-entities/sql
который генерирует полный запрос одним выстрелом.
У вашего запроса, похоже, есть избыточное предложение group by, и я не уверен, откуда происходит имя таблицы dbname
, но следующий запрос должен получить вас на правильном пути.
var query = from mmud in context.updateData
from mmudkv in context.updateDataKeyValue
.Where(x => mmud.updateDataid == x.updateDataId)
.DefaultIfEmpty()
from mmuddk in context.updateDataDetailKey
.Where(x => mmudkv.updateDataDetailKeyid == x.Id)
.DefaultIfEmpty()
where mmud.dbname == "MY_NEW_DB"
where mmudkv.value == "start" || mmudkv.value == "finish"
group mmud by mmud.logDateTime.Date into g
select new
{
Date = g.Key,
Average = EntityFunctions.DiffMilliseconds(g.Max(x => x.logDateTime), g.Min(x => x.logDateTime)),
};
var queryByMonth = from x in query
group x by new { x.Date.Year, x.Date.Month } into x
select new
{
Year = x.Key.Year,
Month = x.Key.Month,
Average = x.Average(y => y.Average)
};
// Single sql statement is to sent to your database
var result = queryByMonth.ToList();
Если у вас все еще есть проблемы, нам нужно будет знать, используете ли вы сущность или linq-to-sql. И вам нужно будет предоставить информацию о вашем контексте/модели