Reputation:
I have two queries in my code:
var query1 = (
from c in db.HugeTableData
where c.price >= 1000
group c by new { c.year, c.month, c.day } into cgroup
select new { Count = cgroup.Count(), cgroup.Key })
.OrderByDescending(x => x.Key.year).ThenByDescending(y => y.Key.month)
.ThenByDescending(z => z.Key.day).Take(50);
//Some other code
var query2 = (
from c in db.HugeTableData
where c.price >= 1000 && c.check == true
group c by new { c.year, c.month, c.day } into cgroup
select new { Count = cgroup.Count(), cgroup.Key })
.OrderByDescending(x => x.Key.year).ThenByDescending(y => y.Key.month)
.ThenByDescending(z => z.Key.day).Take(50);
This two queries are retrieving the qualified records from a table that has a huge amounts of data and as you see the only difference between them is the && c.check == true
part but I'm not looking for how can I refactor it. Unfortunately this code is running very slow, now my question is: is the low performance because two roundtrips to DataBase? And also if I have a huge data, then is Stored Procedure a good choice here?
EDIT: The code that uses these queries is as below:
foreach (var item in query1)
{
DateTime dt = Convert.ToDateTime(item.Key.year + "-" + item.Key.month + "-" + item.Key.day);
string temp = MyConvertToStringMethod(dt);
if (firstDictionary.ContainsKey(temp))
firstDictionary[temp] = item.Count;
}
And also another foreach
for query2
similar to this to fill the secondDictionary
.
Upvotes: 0
Views: 97
Reputation: 16067
You are only retrieving the first 50 records. If the total numbers of records is small and it is possible to hold the complete results in memory, then you could avoid the two round trips to the database by grouping by check, ie
var list = (
from c in db.HugeTableData
where c.price >= 1000
group c by new { c.year, c.month, c.day , c.check } into cgroup
select new {
Count = cgroup.Count(),
cgroup.Key.year ,
cgroup.Key.month,
cgroup.Key.day
}).ToList();
Then you can perform linq-to-objects queries
var query1 = (
from c in list
group c by new { c.year, c.month, c.day } into cgroup
select new { Count = cgroup.Sum(), cgroup.Key })
.OrderByDescending(x => x.Key.year).ThenByDescending(y => y.Key.month)
.ThenByDescending(z => z.Key.day).Take(50);
var query2 = (
from c in list where c.check == true
group c by new { c.year, c.month, c.day } into cgroup
select new { Count = cgroup.Sum(), cgroup.Key })
.OrderByDescending(x => x.Key.year).ThenByDescending(y => y.Key.month)
.ThenByDescending(z => z.Key.day).Take(50);
// Note that you need to use Count=cgroup.Sum()
Upvotes: 1
Reputation: 516
There are several approaches you could take here depending on your scenario. The most widely applicable would be creating a view that implements this logic and then you use it directly. Depending on your Dbms you may be able to speed up this approach further by using indexes. Alternatively if the processing of the results is slow you could look into using the c# yield keyword as you enumerate the results so that the data is processed as it is enumerated.
Upvotes: 0