【问题标题】:Linq to SQL Slow QueryLinq to SQL 慢查询
【发布时间】:2016-06-23 16:22:57
【问题描述】:

我的 ASP.Net 应用程序具有以下 Linq to SQL 函数,用于从产品表中获取不同的高度值列表。

public static List<string> getHeightList(string catID)
        {
            using (CategoriesClassesDataContext db = new CategoriesClassesDataContext())
            {    
                var heightTable = (from p in db.Products
                                   join cp in db.CatProducts on p.ProductID equals cp.ProductID
                                   where p.Enabled == true && (p.CaseOnly == null || p.CaseOnly == false) && cp.CatID == catID
                                   select new { Height = p.Height, sort = Convert.ToDecimal(p.Height.Replace("\"", "")) }).Distinct().OrderBy(s => s.sort);

                List<string> heightList = new List<string>();

                foreach (var s in heightTable)
                {
                    heightList.Add(s.Height.ToString());
                }

                return heightList;
            }
        }

我运行了 Redgate SQL Monitor,它显示此查询正在使用大量资源。

Redgate 还显示我正在运行以下查询:

select count(distinct [height]) from product p 
join catproduct cp on p.productid = cp.productid 
join cat c on cp.catid = c.catid 
where  p.enabled=1 and p.displayfilter = 1 and c.catid = 'C2-14'

我的问题是:

  1. 建议更改函数以减少资源占用?
  2. 另外,linq to sql 如何从我的函数生成上述查询? (我没有在代码的任何地方写 select count(distinct [height]) from product)

产品中有 90,000 条记录。我试图获得不同高度列表的这个类别有 50,000 条产品记录

提前谢谢你,

尼克

【问题讨论】:

  • 将该 SQL 复制到 SQL Server Management Studio 并获取执行计划。将执行计划与您的问题一起发布。 cat.catid 是索引还是键?
  • 您发布的 sql 查询和 linq 查询根本不匹配
  • 您是否在 Management Studio 中尝试过该查询?使用预期执行计划函数对其进行调查。如果您缺少表上的索引,这可能会给您一个提示
  • 如果你不知道如何使用执行计划,你可以看看这里:mssqltips.com/sqlservertutorial/285/query-execution-plans
  • 如果你使用heightTable.ToString(),你应该会得到它将产生的查询。

标签: c# sql-server linq


【解决方案1】:

首先,您发布的 sql 查询和 linq 查询根本不匹配。这不是 LINQ 查询,而是底层 SQL 查询本身执行缓慢。确保JOIN ON子句和WHERE子句和ORDER BY子句中涉及的所有列都正确索引,以便有更好的执行计划;否则你最终会得到一个FULL Table Scan 和一个File Sort 并且查询将被视为执行缓慢。

【讨论】:

  • 我意识到sql查询和linq查询不匹配。我只是想知道 linq to sql 是否会生成额外的查询,因为我在代码中的任何地方都没有看到该 sql 查询。
【解决方案2】:

连接乘以查询返回的Products 的数量。要撤消该操作,请在最后应用 Distinct。如果您立即返回唯一的Products,肯定会减少数据库资源:

var heightTable = (from p in db.Products
                   where p.CatProducts.Any(cp => cp.CatID == catID)
                      && p.Enabled && (p.CaseOnly == null || !p.CaseOnly)
                   select new 
                          {
                              Height = p.Height, 
                              sort = Convert.ToDecimal(p.Height.Replace("\"", ""))
                          }).OrderBy(s => s.sort);

这会将join 更改为where 子句。它省去了数据库引擎对结果进行重复数据删除的麻烦。

如果仍然表现不佳,您应该尝试在内存中进行转换和排序,即在从数据库接收到原始结果之后。

至于计数。我不知道它来自哪里。此类查询通常由 PagedList 等分页库生成,但我在您的代码中看不到任何痕迹。

旁注:您可以返回...

heightList.Select(x => x.Height.ToString()).ToList()

... 而不是自己创建列表。

【讨论】:

  • 感谢 Gert 的帮助,但我仍然需要 distinct,因为可以有多个具有相同高度的产品。
  • 好的,至少这段代码给了 db 引擎一个较小的结果集。
猜你喜欢
  • 2010-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多