我可以进一步优化此查询吗?

时间:2017-02-05 11:56:42

标签: c# sql-server linq linq-to-sql

我的代码中有两个查询:

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);

这两个查询是从具有大量数据的表中检索限定记录,并且您看到它们之间的唯一区别是&& c.check == true部分,但我不是在寻找如何重构它。不幸的是,这段代码运行速度很慢,现在我的问题是:性能是否低,因为两次往返DataBase?而且如果我有大量数据,那么存储过程是一个不错的选择吗?

编辑:使用这些查询的代码如下:

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;
}

另外foreachquery2相似,以填充secondDictionary

2 个答案:

答案 0 :(得分:1)

您只检索前50条记录。如果记录的总数很小并且可以将完整的结果保存在内存中,那么您可以通过检查分组来避免两次往返数据库,即

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();

然后你可以执行linq-to-objects查询

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);

//请注意,您需要使用Count=cgroup.Sum()

答案 1 :(得分:0)

根据您的情况,您可以采取多种方法。最广泛适用的是创建一个实现此逻辑的视图,然后直接使用它。根据您的Dbms,您可以通过使用索引进一步加快此方法。 或者,如果结果处理速度很慢,您可以在枚举结果时使用c#yield关键字,以便在枚举数据时对其进行处理。