Processing math: 100%

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

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
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
分享
相关文章
如何解决 MySQL 数据库服务器 CPU 飙升的情况
大家好,我是 V 哥。当 MySQL 数据库服务器 CPU 飙升时,如何快速定位和解决问题至关重要。本文整理了一套实用的排查和优化套路,包括使用系统监控工具、分析慢查询日志、优化 SQL 查询、调整 MySQL 配置参数、优化数据库架构及检查硬件资源等步骤。通过一个电商业务系统的案例,详细展示了从问题发现到解决的全过程,帮助你有效降低 CPU 使用率,提升系统性能。关注 V 哥,掌握更多技术干货。
189 0
MySQL数据库:基础概念、应用与最佳实践
一、引言随着互联网技术的快速发展,数据库管理系统在现代信息系统中扮演着核心角色。在众多数据库管理系统中,MySQL以其开源、稳定、可靠以及跨平台的特性受到了广泛的关注和应用。本文将详细介绍MySQL数据库的基本概念、特性、应用领域以及最佳实践,帮助读者更好地理解和应用MySQL数据库。二、MySQL
413 5
SQL Server 日期格式查询详解
SQL Server 日期格式查询详解
354 2
jsp中使用Servlet查询SQLSERVER数据库中的表的信息,并且打印在屏幕上
该博客文章介绍了在JSP应用中使用Servlet查询SQL Server数据库的表信息,并通过JavaBean封装图书信息,将查询结果展示在Web页面上的方法。
jsp中使用Servlet查询SQLSERVER数据库中的表的信息,并且打印在屏幕上
JDBC连接SQL Server2008 完成增加、删除、查询、修改等基本信息基本格式及示例代码
这篇文章提供了使用JDBC连接SQL Server 2008数据库进行增加、删除、查询和修改操作的基本步骤和示例代码。
“云端融合:WPF应用无缝对接Azure与AWS——从Blob存储到RDS数据库,全面解析跨平台云服务集成的最佳实践”
【8月更文挑战第31天】本文探讨了如何将Windows Presentation Foundation(WPF)应用与Microsoft Azure和Amazon Web Services(AWS)两大主流云平台无缝集成。通过具体示例代码展示了如何利用Azure Blob Storage存储非结构化数据、Azure Cosmos DB进行分布式数据库操作;同时介绍了如何借助Amazon S3实现大规模数据存储及通过Amazon RDS简化数据库管理。这不仅提升了WPF应用的可扩展性和可用性,还降低了基础设施成本。
159 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` 实现分页查询,便于处理大量数据。这些特性共同提升了开发者的生产力和应用程序的性能。
369 0
绝对干货!从MySQL5.7平滑升级到MySQL8.0的最佳实践分享
绝对干货!从MySQL5.7平滑升级到MySQL8.0的最佳实践分享
423 0

热门文章

最新文章

推荐镜像

更多