我有一个从数据库中提取的详细列表(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; }
}
答案 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()