SQL Server 查询性能不佳

Posted

技术标签:

【中文标题】SQL Server 查询性能不佳【英文标题】:SQL Server query poor performance 【发布时间】:2016-01-18 19:08:16 【问题描述】:

我们正在使用 .NET 应用程序,在该应用程序中,当您按下按钮时,会打开 DevExpress 表单并执行 SQL Server 查询,因此它可以用一些组合框填充数据。应用程序在许多客户中运行良好,但在特定客户中,加载表单需要一分钟多的时间。当我想加载表单时,我可以在性能监视器中看到 SQL Server 占用了大量 CPU。

我直接在 SQL Server Management Studio 中执行了查询,用时不超过一秒钟,但是我尝试查看 SQL Activity Monitor 以及我在此处看到的内容(其他客户不会发生这种情况,相同的 IO,相同的 SQL,一切都一样)是这样的:

所以我在这里看到的但我不明白的是,为什么这个查询有这么多的执行?为什么检索数据需要这么长时间? 这是这个查询的执行计划:

Select * 
From cuinac_pos  
Where [group] in (Select [group] 
                  From proc_groups  
                  Where Code = 13100271)

感谢您为我提供的任何帮助,如果我可以提供更多信息,请不要犹豫。

再次感谢!

添加执行计划建议索引后

查询执行计划

Select count(*) 
From proc_groups 
Where Code = 13100271

proc_groups中索引的定义:

代码示例:

private static void LoadDTPurchaseHerdRelation(Int32 status, Int32 herdNumber)
        
            try
            
                StringBuilder sb = new StringBuilder();


                sb.Append(" Select gr.[group] as HerdId, gr.code as HerdNumber, bo.code as PurchaseCode");
                sb.Append(" From cuinac_pos bo ");
                sb.Append(" inner join proc_groups gr on bo.code=gr.code ");

                if (herdNumber == 0)
                
                    string s1 = " Where (gr.created between '2015-12-09' And '2016-01-08') ";
                    sb.Append(s1);

                    if (status != 4)
                    
                        string s2 = string.Format(" AND bo.purchasestatus = 0 ", status);
                        sb.Append(s2);
                    

                    sb.Append(" order by bo.code ");
                
                else
                
                    string s3 = string.Format(" Where gr.code = '0' ", herdNumber);
                    sb.Append(s3);
                

                DTPurchaseHerdRelation.Clear();
                using (ConnectionScope cs = new ConnectionScope())
                
                    SqlDataAdapter adapter = new SqlDataAdapter(sb.ToString(), (SqlConnection)cs.Connection);
                    adapter.Fill(DTPurchaseHerdRelation);
                
            
            catch (Exception ex)
            

            
        

    

查询的执行计划

Select * From cuinac_pos Where [group] in (Select [group] From proc_groups Where Code = N'13100271')

已解决:

我终于通过添加标记为正确的答案中建议的索引,并在代码中添加了它,在通过 nvarchar 值“代码”搜索的查询中,在 shriop 在 cmets 中建议的 rhe 值之前的 N。谢谢大家的努力!

【问题讨论】:

在第二张截图中,不是要求您在 cuinac_pos.group 列上创建索引吗? 右键单击执行计划并选择缺失的索引。这将为您提供索引脚本。然后再试一次 我需要几条信息来提供帮助。从 proc_groups 中选择 count() 其中代码 = 13100271。从 proc_groups 中选择 count()。代码是什么数据类型? Select count(*) From proc_groups Where Code = 13100271 的执行计划是什么?为更简单的查询修复计划是下一个问题,以使其不进行“索引扫描”。 你确定你的代码中没有一个循环为一页调用多次吗? 我更改了查询,所以不,我没有看到上面的执行计划,也没有看到更改后的查询。 “选择 * From cuinac_pos Where [group] in (Select [group] From proc_groups Where Code = N'13100271')”。关键部分是在单引号内运行它,并在单引号前加上字母 N。这将其定义为 NVARCHAR 值。如果您查看您提供的悬停屏幕截图,它会显示一个阻止使用索引的 CONVERT_IMPLICIT。在查询和代码中进行更改是试图删除它。 【参考方案1】:

对于这个查询:

Select *
From cuinac_pos
Where [group] in (Select [group] From proc_groups  Where Code = 13100271 );

最佳索引是proc_groups(code, group)cuinac_pos(group)。拥有这些索引可能会有所帮助。

编辑:

就性能而言,这可能会更好:

Select *
From cuinac_pos cp
Where exists (Select 1
              From proc_groups pg
              Where pg.Code = 13100271 and pg.[group] = cp.[group]
             );

在 `proc_groups(group, code) 上有一个索引

【讨论】:

感谢您的帮助,我已经添加了执行计划中建议的索引,但是仍然非常非常慢。 修改代码是我们最后的选择,因为它可以在除这个客户端之外的所有客户端中工作,此时我们将尝试在 SQL 中进行更改。不过,感谢您的建议,也许我们最后需要对代码进行一些修改!【参考方案2】:

每当我读到“SSMS 速度快但应用程序慢”之类的内容时,我都必须考虑这一点:

http://www.sommarskog.se/query-plan-mysteries.html

这尤其适用于较旧的数据库,从 SQL Server 版本到 SQL Server 版本存在并通过脚本升级,并且通过存储过程完成数据读取。

大多数情况下,这种行为可以通过将SET ARITHABORT ON 作为 SQL 代码的第一行来解决。

您可以将其直接放入您的 SP,或通过 Connection 在您的应用程序中将其设置为默认值。

祝你好运,编码愉快

【讨论】:

以上是关于SQL Server 查询性能不佳的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 性能不佳,有很多 OR 和使用 UPPER() 的重复条件

性能不佳的 SQL 查询

索引视图以提高 SQL Server 上多个连接的性能

为啥使用 EF / Linq to sql 创建性能不佳的查询如此容易[关闭]

SQL Server:将多行合并为 1 行

PHP 循环 - SQL 性能不佳