Reputation: 732
I have a large database query that returns around 100k
records into an in-memory list. I need to link a list of related employees to each record (also around 100k
records), but I'm struggling to get useable performance.
foreach (var detail in reportData.Details)
{
detail.Employees = employees
.Where(x => x.AccountingDocumentItemId == detail.AccountingDocumentItemId)
.Select(x => x.Employee)
.ToList();
detail.Employee = String.Join(", ", detail.Employees);
}
The above code takes over 8 minutes to complete. I've narrowed down the speed issue to the first line in the for loop
where it finds the related employees. If I leave out the ToList()
it's super fast, but then the next line immediately causes the issues where the String.Join
causes the Where to execute.
I'm obviously approaching this from the wrong angle, but I've exhausted the options I think would work.
Upvotes: 2
Views: 295
Reputation: 186803
You current code has O(n ** 2)
time complexity (nested loops) and thus you have 1e5 * 1e5 ~ 1e10
(10 billions) operations to perform which takes 8
minutes to complete.
Let's extract a dictionary in order to have O(n)
time complexity (~1e5
operations only):
var dict = reportData
.Details
.GroupBy(item => item.AccountingDocumentItemId,
item => item.Employee)
.ToDictionary(chunk => chunk.Key,
chunk => chunk.ToList());
foreach (var detail in reportData.Details) {
detail.Employees = dict.TryGetValue(detail.AccountingDocumentItemId, out var list)
? list.ToList() // copy of the list
: new List<MyClass>(); // put the right type instead of MyType
detail.Employee = String.Join(", ", detail.Employees);
}
Upvotes: 6