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

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介: # 摘要 阿里云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
AI 代码解读

从性能指标来看,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
AI 代码解读

优化后性能指标,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
AI 代码解读

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

RTRIM

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

IF 'TRIM ' = 'TRIM'
    PRINT 'equals'
ELSE
    PRINT 'not equal'
AI 代码解读

结果展示如下图所示:
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查询的改写方法。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
打赏
0
0
0
2
9296
分享
相关文章
基于SQL Server / MySQL进行百万条数据过滤优化方案
对百万级别数据进行高效过滤查询,需要综合使用索引、查询优化、表分区、统计信息和视图等技术手段。通过合理的数据库设计和查询优化,可以显著提升查询性能,确保系统的高效稳定运行。
55 9
MySQL/SqlServer跨服务器增删改查(CRUD)的一种方法
通过上述方法,MySQL和SQL Server均能够实现跨服务器的增删改查操作。MySQL通过联邦存储引擎提供了直接的跨服务器表访问,而SQL Server通过链接服务器和分布式查询实现了灵活的跨服务器数据操作。这些技术为分布式数据库管理提供了强大的支持,能够满足复杂的数据操作需求。
168 12
突破T-SQL限制:利用CLR集成扩展RDS SQL Server的功能边界
CLR集成为SQL Server提供了强大的扩展能力,突破了T-SQL的限制,极大地拓展了SQL 的应用场景,如:复杂字符串处理、高性能计算、图像处理、机器学习集成、自定义加密解密等,使开发人员能够利用 .NET Framework的丰富功能来处理复杂的数据库任务。
SQL Server 日期格式查询详解
SQL Server 日期格式查询详解
352 2
创建包含MySQL和SQLServer数据库所有字段类型的表的方法
创建一个既包含MySQL又包含SQL Server所有字段类型的表是一个复杂的任务,需要仔细地比较和转换数据类型。通过上述方法,可以在两个数据库系统之间建立起相互兼容的数据结构,为数据迁移和同步提供便利。这一过程不仅要考虑数据类型的直接对应,还要注意特定数据类型在不同系统中的表现差异,确保数据的一致性和完整性。
81 4
JDBC连接SQL Server2008 完成增加、删除、查询、修改等基本信息基本格式及示例代码
这篇文章提供了使用JDBC连接SQL Server 2008数据库进行增加、删除、查询和修改操作的基本步骤和示例代码。
数据库空间之谜:彻底解决RDS for SQL Server的空间难题
【8月更文挑战第16天】在管理阿里云RDS for SQL Server时,合理排查与解决空间问题是确保数据库性能稳定的关键。常见问题包括数据文件增长、日志文件膨胀及索引碎片累积。利用SQL Server的动态管理视图(DMV)可有效监测文件使用情况、日志空间及索引碎片化程度。例如,使用`sp_spaceused`检查文件使用量,`sys.dm_db_log_space_usage`监控日志空间,`sys.dm_db_index_physical_stats`识别索引碎片。同时,合理的备份策略和文件组设置也有助于优化空间使用,确保数据库高效运行。
189 2
从零到英雄:一步步构建你的首个 JSF 应用程序,揭开 JavaServer Faces 的神秘面纱
【8月更文挑战第31天】JavaServer Faces (JSF) 是一种强大的 Java EE 标准,用于构建企业级 Web 应用。它提供了丰富的组件库和声明式页面描述语言 Facelets,便于开发者快速开发功能完善且易于维护的 Web 应用。本文将指导你从零开始构建一个简单的 JSF 应用,包括环境搭建、依赖配置、Managed Bean 编写及 Facelets 页面设计。
148 0
Play Framework的安全面纱:揭开隐藏在优雅代码下的威胁
【8月更文挑战第31天】Play Framework 是一款高效、轻量级的 Web 开发框架,内置多种安全特性,助力开发者构建安全稳定的应用。本文详细介绍 Play 如何防范 SQL 注入、XSS 攻击、CSRF 攻击,并提供安全的密码存储方法及权限管理策略,通过具体示例代码展示实施步骤,助您有效抵御常见威胁。
94 0
Entity Framework Core 与 SQL Server 携手,高级查询技巧大揭秘!让你的数据操作更高效!
【8月更文挑战第31天】Entity Framework Core (EF Core) 是一个强大的对象关系映射(ORM)框架,尤其与 SQL Server 数据库结合使用时,提供了多种高级查询技巧,显著提升数据操作效率。它支持 LINQ 查询,使代码简洁易读;延迟加载与预先加载机制优化了相关实体的加载策略;通过 `FromSqlRaw` 或 `FromSqlInterpolated` 方法支持原始 SQL 查询;可调用存储过程执行复杂任务;利用 `Skip` 和 `Take` 实现分页查询,便于处理大量数据。这些特性共同提升了开发者的生产力和应用程序的性能。
362 0
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等