LINQ to Objects Performance - 用于长时间运行的巨大数据集

时间:2014-03-26 16:35:44

标签: c# linq

我有一个从数据库中提取的详细列表(200,000条记录),我需要找到每个细节的位置,下面是循环遍历详细列表并为列表分配位置的代码。此循环执行时间超过15分钟,但如果不填充Locations属性,则只需不到一分钟。

如何优化此代码?

class Program
{
    static void Main(string[] args)
    {
        List<Details> databaseDetailList = GetDetailsFromdatabase();
        List<Location1> databaseLocation1List = GetLocations1Fromdatabase();
        List<Location2> databaseLocation2List = GetLocations2Fromdatabase();

        List<Details> detailList = new List<Details>();
        foreach (var x in databaseDetailList)
        {
            detailList.Add(new Details
            {
                DetailId = x.DetailId,
                Code = x.Code,
                //If I comment out the Locations then it works faster
                Locations = new LocationIfo {
                    Locations1 = databaseLocation1List
                                .Where(l=>l.DetailId == x.DetailId && l.Code == x.Code).ToList(),
                    Locations2 = databaseLocation2List
                                .Where(l => l.DetailId == x.DetailId && l.Code == x.Code).ToList()
                }
            });
        }
    }

    private static List<Details> GetDetailsFromdatabase()
    {
        //This returns 200,000 records from database
        return new List<Details>();
    }

    private static List<Location1> GetLocations1Fromdatabase()
    {
        //This returns 100,000 records from database
        return new List<Location1>();
    }

    private static List<Location2> GetLocations2Fromdatabase()
    {
        //This returns 100,000 records from database
        return new List<Location2>();
    }
}

public class Details
{
    public string DetailId { get; set; }
    public string Code { get; set; }
    public LocationIfo Locations { get; set; }
}

public class LocationIfo
{
    public List<Location1> Locations1 { get; set; }
    public List<Location2> Locations2 { get; set; }
}

public class Location1
{
    public int LocationId { get; set; }
    public string DetailId { get; set; }
    public string Code { get; set; }
    public string OtherProperty { get; set; }
}

public class Location2
{
    public int LocationId { get; set; }
    public string DetailId { get; set; }
    public string Code { get; set; }
    public string OtherProperty { get; set; }
}

3 个答案:

答案 0 :(得分:4)

您在概念上做的是Join。使用正确的操作将确保它更有效地执行。理想情况下,您甚至可以在数据库方面执行Join,而不是将所有数据下拉到列表中,但即使您确实将所有数据都拉下来,也可以使用{{ 1}} 很多效率更高。

Join

答案 1 :(得分:0)

这有点苛刻 - 但你可以使用查找:

如果代码的查找部分花费的时间最长 - 并且您无法更改数据库代码(如加入建议的那样),您可以考虑为{{1}编制索引在内存中查找返回类型。

构建一个查找键,它是两个值的组合 - 根据您的要求,这需要具体唯一。

Location

然后:

DetailId-Code - "123123-343"


private static ILookup<int, Location1> GetLocations1Fromdatabase()
{
    //This returns 100,000 records from database
    return new List<Location2>()
        .ToLookup(l => l.DetailId + "-" + l.Code);
}

答案 2 :(得分:0)

这是a very similar problem我几天前(在Ruby中)。 最后,我找到的最佳解决方案是将List(或Array)转换为Dictionary(或Hash)

创建一个字典,将搜索字段连接为键,列表项连接为值:

var dict1 = databaseLocation1List.ToDictionary(x => x.DetailId.ToString() + x.Code.ToString(), x);

然后按键字典中的搜索将非常快:

Locations1 = dict1[x.DetailId.ToString() + x.Code.ToString()].ToList()