RDS SQL Server - 最佳实践 - 高CPU使用率系列之非SARG查询

本文涉及的产品
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
云数据库 RDS SQL Server,独享型 2核4GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
简介: # 摘要 阿里云RDS SQL Server客户遇到最多的一个问题便是高CPU使用率导致导致SQL Server服务响应缓慢,查询超时,甚至服务挂起僵死。本系列文章第四篇分析非SARG查询导致CPU的高利用率的解决之道。 # 问题引入 “鸟啊,你听说过RDBMS的非SARG查询语句吗?我还是今天第一次听说呢!”。老鸟有些不解的问菜鸟。 “哈哈,鸟哥,孤陋寡闻,土鳖了吧。它可是导致RDBMS

摘要

阿里云RDS SQL Server客户遇到最多的一个问题便是高CPU使用率导致导致SQL Server服务响应缓慢,查询超时,甚至服务挂起僵死。本系列文章第四篇分析非SARG查询导致CPU的高利用率的解决之道。

问题引入

“鸟啊,你听说过RDBMS的非SARG查询语句吗?我还是今天第一次听说呢!”。老鸟有些不解的问菜鸟。
“哈哈,鸟哥,孤陋寡闻,土鳖了吧。它可是导致RDBMS数据库CPU高使用率的又一个重要的原因呢!今天就让我细细道来。”,菜鸟开始得意忘形起来。”。

场景分析

SARG是Search Argument英文的缩写形式,非SARG简单来说就是指查询谓词(特别是WHERE字句或者连接操作的ON字句)导致索引失效,查询优化器无法使用高效的Index Seek操作,退而求其次的使用效率相对较低的Index Scan操作,从而导致了CPU使用率的上升和查询性能降低。常见的非SARG操作包括在WHERE语句中使用到了标量函数Datediff,Dateadd,Year,Rtrim,Upper,Lower,LIKE完全模糊匹配(格式如LIKE ‘%XXX%’)或者是用户自定义函数等。

解决方法

解决非SARG查询的核心思想是通过查询逻辑的等价改写或者功能设计层面的优化来避免WHERE语句中使用标量函数,我们仅以以下几种常见的非SARG操作来举例说明,其他类推。

DATEDIFF

比如,我们需要查询出当天的订单信息记录,非SARG的写法如下(在WHERE语句中使用了Datediff函数):

USE TestDb
GO

CREATE INDEX IX_OrderDate
ON dbo.SalesOrder([OrderDate])
WITH (FILLFACTOR = 90);
GO

SET STATISTICS TIME ON
SET STATISTICS IO ON

-- find out sales info of today.
SELECT 
    ItemID, OrderQty, Price,OrderDate
FROM dbo.SalesOrder
WHERE DATEDIFF(DAY, OrderDate, GETDATE()) = 0

SET STATISTICS TIME OFF
SET STATISTICS IO OFF

从性能指标来看,I/O消耗为8406,CPU消耗为171毫秒,执行时间消耗为211毫秒,截图如下所示:
01.png

执行计划窗口,SQL Server优化器选择走Index Scan,截图如下:
02.png

其实,我们可以换个思维逻辑想想,当天的数据,其实是指时间大于等于当天凌晨零点零分,并且时间小于等于当前时刻的记录。那么等价逻辑的改写代码如下:

USE TestDb
GO
SET STATISTICS TIME ON
SET STATISTICS IO ON

DECLARE
    @today DATETIME = CONVERT(CHAR(10), GETDATE(), 120)
;
SELECT 
    ItemID, OrderQty, Price,OrderDate
FROM dbo.SalesOrder
WHERE OrderDate >= CONVERT(CHAR(10), GETDATE(), 120)
    AND OrderDate <= GETDATE();
SET STATISTICS TIME OFF
SET STATISTICS IO OFF

优化后性能指标,I/O消耗为3,CPU消耗为0毫秒,执行时间消耗为109毫秒。
03.png

查询优化器选择了更为高效的Index Seek的执行计划操作上来,截图如下:
04.png

从性能指标对比来看,I/O从8406降低到3,CPU消耗从171毫秒降低到0毫秒,执行时间从211降低到109毫秒,特别是I/O和CPU的提升非常明显。

UPPER/LOWER

由于SQL Server默认的排序规则是忽略大小写的,换句话说SQL Server认为UPPER和upper是相等的。所以在做字符串比较运算的时候,可以省略UPPER或者是LOWER函数的使用,以免造成非SARG查询,导致CPU使用率增加。
当然需要特别注意的是:在改写非SARG查询之前需要再次确认你的数据库是忽略大小写的,即含有case-insensitive关键字。检查方法如下:

USE TestDb
GO
EXEC sys.sp_helpsort

结果展示如下图所示:
05.png

RTRIM

有的人在写字符串比较的时候,喜欢使用RTRIM函数来取消字符串最右边的空格后再来比较,其实这种做法是画蛇添足,完全没有必要的。理由是SQL Server在做字符串比较的时候,自动会忽略最右边的空格。这样做反而会导致非SARG查询,CPU使用率增高。
我们可以写一个非常简单的例子来证明这一点,在IF语句中,等号左边的RTRIM后紧跟一个空格符,等号右边的字符串TRIM后不包括空格,但是IF语句的判断结果为真。代码如下所示:

IF 'TRIM ' = 'TRIM'
    PRINT 'equals'
ELSE
    PRINT 'not equal'

结果展示如下图所示:
06.png

LIKE完全模糊匹配

WHERE语句中的LIKE完全模糊匹配,同样会导致SQL Server索引失效,同样也是属于非SARG查询的一种。这种场景的优化包含两种方法:第一种方法是从设计层面来优化,比如:我们经常碰到的场景是通过电话号码来完全模糊查询,但是客户的查询语句往往传入的电话号码又都是一个完整的电话号码。所以这里,我们完全可以将设计修改为电话号码仅支持完整电话号码查询,即将LIKE完全模糊匹配的设计修改成了等于操作方式,避免了非SARG操作;第二种解决方法:如果设计层面无法避免要使用完全模糊匹配查询,可以选择使用SQL Server Fulltext技术来解决LIKE字句完全模糊查询,以此来避免非SARG操作,降低CPU使用率。详情,可以参见文章:SQL Server FullText解决Like字句性能问题

总结

本篇文章分析了非SARG查询语句导致RDS SQL Server CPU使用率增高的原因以及解决这类问题的核心思想是改写语义逻辑,避免非SARG查询导致CPU高使用率,并且举例说明了几个典型的非SARG查询的改写方法。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
3天前
|
SQL 存储 监控
SQL Server的并行实施如何优化?
【7月更文挑战第23天】SQL Server的并行实施如何优化?
25 13
|
21小时前
|
关系型数据库 分布式数据库 数据库
PolarDB产品使用问题之将RDS切换到PolarDB-X 2.0时,代码层的SQL该如何改动
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
7天前
|
存储 SQL C++
对比 SQL Server中的VARCHAR(max) 与VARCHAR(n) 数据类型
【7月更文挑战7天】SQL Server 中的 VARCHAR(max) vs VARCHAR(n): - VARCHAR(n) 存储最多 n 个字符(1-8000),适合短文本。 - VARCHAR(max) 可存储约 21 亿个字符,适合大量文本。 - VARCHAR(n) 在处理小数据时性能更好,空间固定。 - VARCHAR(max) 对于大文本更合适,但可能影响性能。 - 选择取决于数据长度预期和业务需求。
|
11天前
|
SQL Oracle 关系型数据库
MySQL、SQL Server和Oracle数据库安装部署教程
数据库的安装部署教程因不同的数据库管理系统(DBMS)而异,以下将以MySQL、SQL Server和Oracle为例,分别概述其安装部署的基本步骤。请注意,由于软件版本和操作系统的不同,具体步骤可能会有所变化。
45 3
|
17天前
|
SQL 存储 安全
数据库数据恢复—SQL Server数据库出现逻辑错误的数据恢复案例
SQL Server数据库数据恢复环境: 某品牌服务器存储中有两组raid5磁盘阵列。操作系统层面跑着SQL Server数据库,SQL Server数据库存放在D盘分区中。 SQL Server数据库故障: 存放SQL Server数据库的D盘分区容量不足,管理员在E盘中生成了一个.ndf的文件并且将数据库路径指向E盘继续使用。数据库继续运行一段时间后出现故障并报错,连接失效,SqlServer数据库无法附加查询。管理员多次尝试恢复数据库数据但是没有成功。
|
22天前
|
SQL 存储 关系型数据库
关系型数据库SQL Server学习
【7月更文挑战第4天】
26 2
|
5天前
|
SQL 监控 数据库
SQL Server 查询超时问题排查
【7月更文挑战第8天】排查 SQL Server 查询超时涉及五个主要方面:检查复杂查询、评估服务器性能、审视配置参数、更新统计信息和分析执行计划。关注点包括查询的结构(如连接、子查询和索引),服务器资源(CPU、内存、网络延迟),连接和内存设置,以及统计信息的时效性。通过这些步骤可定位并解决性能瓶颈。
|
7天前
|
SQL 存储 Oracle
TDengine 3.3.2.0 发布:新增 UDT 及 Oracle、SQL Server 数据接入
**TDengine 3.3.2.0 发布摘要** - 开源与企业版均强化性能,提升WebSocket、stmt模式写入与查询效率,解决死锁,增强列显示。 - taos-explorer支持geometry和varbinary类型。 - 企业版引入UDT,允许自定义数据转换。 - 新增Oracle和SQL Server数据接入。 - 数据同步优化,支持压缩,提升元数据同步速度,错误信息细化,支持表名修改。 - 扩展跨平台支持,包括麒麟、Euler、Anolis OS等。
18 0
|
11天前
|
存储 关系型数据库 MySQL
MySQL小白教程(进阶篇):数据管理与高级查询
MySQL小白教程(进阶篇):数据管理与高级查询
|
11天前
|
存储 关系型数据库 MySQL
MySQL小白教程:从入门到查询高手
MySQL小白教程:从入门到查询高手