簡體   English   中英

LINQ查詢檢索耗時過長的數據

[英]LINQ query to retrieve pivoted data taking too long

我正在處理一個LINQ查詢,其中包括一些數據如下

var q = data.GroupBy(x => new
            {
                x.Med.Name,
                x.Med.GenericName,             
            }).ToList().Select(g =>
                new SummaryDto
                {
                    Name= g.Key.Name,
                    GenericName = g.Key.GenericName,                    
                    Data2012 = g.Where(z => z.ProcessDate.Year == 2012).Count(),
                    Data2013 = g.Where(z => z.ProcessDate.Year == 2013).Count(),
                    Data2014 = g.Where(z => z.ProcessDate.Year == 2014).Count(),
                    Data2015 = g.Where(z => z.ProcessDate.Year == 2015).Count(),
                    Data2016 = g.Where(z => z.ProcessDate.Year == 2016).Count(),
                    Data2017 = g.Where(z => z.ProcessDate.Year == 2017).Count(),
                    TotalCount = g.Count(),
                }).AsQueryable();

            return q;

上面的LINQ花費很長時間,因為它查詢了grp q.Count()*6 times 如果有10000條記錄,那么它將查詢60000次。 是否有更好的方法可以更快地進行記錄?

將年份添加到組密鑰中,然后再次進行分組,然后按組計數進行收獲:

return data.GroupBy(x => new {
    x.Med.Name
,   x.Med.GenericName
,   x.ProcessDate.Year
}).Select(g => new {
    g.Key.Name
,   g.Key.GenericName
,   g.Key.Year
,   Count = g.Count()
}).GroupBy(g => new {
    g.Name
,   g.GenericName
}).Select(g => new SummaryDto {
    Name = g.Key.Name
,   GenericName = g.Key.GenericName
,   Data2012 = g.SingleOrDefault(x => x.Year == 2012)?.Count ?? 0
,   Data2013 = g.SingleOrDefault(x => x.Year == 2013)?.Count ?? 0
,   Data2014 = g.SingleOrDefault(x => x.Year == 2014)?.Count ?? 0
,   Data2015 = g.SingleOrDefault(x => x.Year == 2015)?.Count ?? 0
,   Data2016 = g.SingleOrDefault(x => x.Year == 2016)?.Count ?? 0
,   Data2017 = g.SingleOrDefault(x => x.Year == 2017)?.Count ?? 0
,   TotalCount = g.Sum(x => x.Count)
}).AsQueryable();

注意:這種方法是有問題的,因為年份是在SummaryDto類中硬編碼的。 您最好將DTO構造函數傳遞給IDictionary<int,int>其中包含每年的計數。 如果進行此更改,則最終的Select(...)將如下所示:

.Select(g => new SummaryDto {
    Name = g.Key.Name
,   GenericName = g.Key.GenericName
,   TotalCount = g.Sum(x => x.Count)
,   DataByYear = g.ToDictionary(i => i.Year, i => i.Count)
}).AsQueryable();

我建議按年份在組內分組,然后轉換為詞典以訪問計數。 首先進行年度分組然后在內存中進行計數是否更快,取決於初始分組的分布,但是對於數據庫而言,可能取決於其按年度分組的效率,因此我將進行測試以確定哪個似乎最快。

無論如何,在初始分組之后按年份分組比內存中的查詢快約33%,但同樣,它很大程度上取決於分布。 隨着初始組數的增加,按年份查詢的分組速度將降低,以匹配原始查詢。 請注意,沒有任何年份計數的原始查詢大約是時間的1/3。

下面是數據庫分組之后的分組:

var q = data.GroupBy(x => new {
    x.Med.Name,
    x.Med.GenericName,
}).ToList().Select(g => {
    var gg = g.GroupBy(d => d.ProcessDate.Year).ToDictionary(d => d.Key, d => d.Count());
    return new SummaryDto {
        Name = g.Key.Name,
        GenericName = g.Key.GenericName,
        Data2012 = gg.GetValueOrDefault(2012),
        Data2013 = gg.GetValueOrDefault(2013),
        Data2014 = gg.GetValueOrDefault(2014),
        Data2015 = gg.GetValueOrDefault(2015),
        Data2016 = gg.GetValueOrDefault(2016),
        Data2017 = gg.GetValueOrDefault(2017),
        TotalCount = g.Count(),
    };
}).AsQueryable();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM