RDS SQL Server - 专题分享 - 巧用执行计划缓存之Table Scan

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介: # 背景引入 执行计划中的Table Scan或者是Clustered Index Scan会导致非常低下的查询性能,尤其是对于大表或者超大表。执行计划缓存是SQL Server内存管理中非常重要的特性,这篇系列文章我们探讨如何从执行计划缓存的角度来发现RDS SQL数据库引擎中的Table Scan行为,以及与之相应SQL查询语句详细信息。 # 问题分析 其实,我们大家都知道,Table

背景引入

执行计划中的Table Scan或者是Clustered Index Scan会导致非常低下的查询性能,尤其是对于大表或者超大表。执行计划缓存是SQL Server内存管理中非常重要的特性,这篇系列文章我们探讨如何从执行计划缓存的角度来发现RDS SQL数据库引擎中的Table Scan行为,以及与之相应SQL查询语句详细信息。

问题分析

其实,我们大家都知道,Table Scan或者Clustered Index Scan是关系型数据库查询性能很差的一种表扫描查询方式,如果在数据库引擎中存在大量的Table Scan行为的话,一般数据库性能都不会好到哪里去。在阿里云RDS SQL产品中,我们可以很简单的查看发生在RDS SQL引擎中的Table Scan频率,方法是:在阿里云控制台 云数据库RDS版 => 实例列表 => 打开对应的RDS SQL实例(在此以RDS SQL 2008R2版本为例)=> 监控与报警 => 引擎监控
01.png

往下拉动滚动条,会看到性能指标“平均每秒全表扫描次数”,表示发生在RDS SQL 2008R2数据库引擎中平均每秒表扫描的次数。
02.png

在很多次性能优化的案例中,我们告诉客人:“您的RDS 实例中,存在很多Table Scan行为,导致查询效率低下”,这时候客户会立马反问:那您知道我的哪些查询语句导致了Table Scan操作吗?今天这篇文章就是分享这个问题的解法:我们从执行计划缓存的角度来获取哪些查询语句导致了RDS SQL数据库引擎的Table Scan行为。

测试脚本

为了模拟出RDS SQL数据库引擎执行查询语句使用Table Scan的行为,我们创建一张没有任何Index,没有主键的表,接下来初始化10000条数据,然后循环执行查询语句和存储过程。测试的代码如下所示:

USE TestDb
GO

-- create demo table TestTableScan
IF OBJECT_ID('dbo.TestTableScan', 'U') IS NOT NULL
BEGIN
    DROP TABLE dbo.TestTableScan
END
GO

CREATE TABLE dbo.TestTableScan
(
    RowID INT IDENTITY(1,1) NOT NULL
    , OrderID UNIQUEIDENTIFIER NOT NULL
    , ItemID INT NOT NULL
);

-- data init for 10000 records.
;WITH a 
AS (
    SELECT * 
    FROM (VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) AS a(a)
), RoundData
AS(
SELECT TOP(10000)
    OrderID = NEWID()
    ,ItemIDRound = abs(checksum(newid()))
    ,Price = a.a * b.a * 10
    ,OrderQty = a.a + b.a + c.a + d.a + e.a + f.a + g.a + h.a
FROM a, a AS b, a AS c, a AS d, a AS e, a AS f, a AS g, a AS h
)
INSERT INTO dbo.TestTableScan(OrderID, ItemID)
SELECT 
    OrderID
    ,ItemID = cast(ROUND((1300 * (ItemIDRound*1./cast(replace(ItemIDRound, ItemIDRound, '1' + replicate('0', len(ItemIDRound))) as bigint)) + 101), 0) as int)
FROM RoundData

GO


--Test ADHOC
DECLARE
    @do INT = 0
    ,@loop INT = 5;
WHILE @do < @loop
BEGIN
    SELECT * FROM dbo.TestTableScan AS A
        INNER JOIN dbo.TestTableScan AS B
        ON A.ItemID = B.ItemID

    SET @do = @do + 1;
END
GO

--Call Store Procedure Testing
CREATE PROC dbo.UP_TableScanTesting
AS
BEGIN
    SET NOCOUNT ON
    SELECT * FROM dbo.TestTableScan AS A
        INNER JOIN dbo.TestTableScan AS B
        ON A.ItemID = B.ItemID

    SELECT TOP 1 * FROM sys.objects
    where object_id = @@PROCID
END
GO

EXEC dbo.UP_TableScanTesting
GO

解决方法

首先,我们可以动态视图sys.dm_exec_query_stats中根据每一个查询的plan_handle来统计该查询的执行次数、总共耗时、总的逻辑读、写、总共CPU时间消耗等信息;然后通过执行计划缓存函数sys.dm_exec_query_plan来分析相应的查询语句的详细信息。详情脚本参加如下代码:

-- Generate all query SQL text with "table scan" in cached query plan 
;WITH  XMLNAMESPACES 
    (DEFAULT N'http://schemas.microsoft.com/sqlserver/2004/07/showplan'   
            ,N'http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS ShowPlan)
,EQS 
AS (
    SELECT EQS.plan_handle 
           ,SUM(EQS.execution_count) AS ExecutionCount 
           ,SUM(EQS.total_worker_time) AS TotalWorkTime 
           ,SUM(EQS.total_logical_reads) AS TotalLogicalReads 
           ,SUM(EQS.total_logical_writes) AS TotalLogicalWrites 
           ,SUM(EQS.total_elapsed_time) AS TotalElapsedTime 
           ,MAX(EQS.last_execution_time) AS LastExecutionTime 
     FROM sys.dm_exec_query_stats AS EQS 
     GROUP BY EQS.plan_handle
), info
AS(
    SELECT DISTINCT
        EQS.[ExecutionCount] 
        ,EQS.[TotalWorkTime] 
        ,EQS.[TotalLogicalReads] 
        ,EQS.[TotalLogicalWrites] 
        ,EQS.[TotalElapsedTime] 
        ,EQS.[LastExecutionTime] 
        ,ScanObject = StmtSimple.Node.value('(QueryPlan/RelOp//RelOp//TableScan/Object/@Database)[1]','sysname') + '.' +
                    StmtSimple.Node.value('(QueryPlan/RelOp//RelOp//TableScan/Object/@Schema)[1]','sysname') + '.' +
                    StmtSimple.Node.value('(QueryPlan/RelOp//RelOp//TableScan/Object/@Table)[1]','sysname')
        ,Statement = StmtSimple.Node.value('(@StatementText)[1]', 'nvarchar(max)')
        ,EST.text
        ,ECP.[objtype] AS [ObjectType] 
        ,ECP.[cacheobjtype] AS [CacheObjectType]
        ,EQS.plan_handle
    FROM sys.dm_exec_cached_plans AS ECP
        INNER JOIN EQS
        ON ECP.plan_handle = EQS.plan_handle
        CROSS APPLY sys.dm_exec_sql_text(ECP.[plan_handle]) AS EST
        CROSS APPLY sys.dm_exec_query_plan(ECP.[plan_handle]) AS EQP
        CROSS APPLY EQP.query_plan.nodes('/ShowPlanXML/BatchSequence/Batch/Statements/StmtSimple') AS StmtSimple(Node)
    WHERE StmtSimple.Node.exist('data(QueryPlan/RelOp//RelOp[@PhysicalOp="Table Scan"])') = 1
)
SELECT A.*, EQP.query_plan
FROM info AS A
    CROSS APPLY sys.dm_exec_query_plan(A.[plan_handle]) AS EQP
ORDER BY A.TotalElapsedTime DESC, A.ExecutionCount

执行上面的查询,结果展示如下图所示:
03.png

从分析结果的截图来看,我们可以得到很多有用的信息,比如:
每个查询语句的执行次数、总执行耗时、逻辑读写、对应Table Scan的查询Statement和详细的查询Batch语句,以及详细的执行计划等有用信息。

最后总结

这篇文章讨论了如何从执行计划缓存中找到Table Scan查询语句的详情,利用这个方法可以很轻松的找到RDS SQL客户需要的答案。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
8天前
|
SQL 开发框架 .NET
突破T-SQL限制:利用CLR集成扩展RDS SQL Server的功能边界
CLR集成为SQL Server提供了强大的扩展能力,突破了T-SQL的限制,极大地拓展了SQL 的应用场景,如:复杂字符串处理、高性能计算、图像处理、机器学习集成、自定义加密解密等,使开发人员能够利用 .NET Framework的丰富功能来处理复杂的数据库任务。
|
2月前
|
SQL 关系型数据库 MySQL
MySQL 8.0报错--1118-Row size too large. The maximum row size for the used table type, not counting BLOBs,is 8126,
MySQL 8.0报错--1118-Row size too large. The maximum row size for the used table type, not counting BLOBs,is 8126,
MySQL 8.0报错--1118-Row size too large. The maximum row size for the used table type, not counting BLOBs,is 8126,
|
1月前
|
SQL 关系型数据库 MySQL
MySQL异常一之: You can‘t specify target table for update in FROM clause解决办法
这篇文章介绍了如何解决MySQL中“不能在FROM子句中指定更新的目标表”(You can't specify target table for update in FROM clause)的错误,提供了错误描述、需求说明、错误做法和正确的SQL写法。
471 0
|
6月前
|
SQL 存储 关系型数据库
RDS for MySQL的SQL分类与数据类型
小明需在MySQL中管理商品信息,使用SQL完成业务操作。SQL分为DQL(查询)、DML(增删改)、DDL(定义)、DCL(权限控制)和TCL(事务)五大类。DDL用于创建、修改和删除数据库结构,DML处理数据,DCL控制权限,TCL管理事务,DQL则用于查询数据。MySQL有多种数据类型,如数值型(整数、小数)、日期型和字符串型等,选择合适的数据类型是高效开发的关键。
70 0
|
3月前
|
SQL 关系型数据库 数据库
数据库空间之谜:彻底解决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`识别索引碎片。同时,合理的备份策略和文件组设置也有助于优化空间使用,确保数据库高效运行。
86 2
|
4月前
|
关系型数据库 分布式数据库 数据库
PolarDB产品使用问题之将RDS切换到PolarDB-X 2.0时,代码层的SQL该如何改动
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
5月前
|
关系型数据库 MySQL 数据库
【MySQL】MySQL数据库的delete from table和truncate table之间的区别
【MySQL】MySQL数据库的delete from table和truncate table之间的区别
631 1
|
5月前
|
缓存 分布式计算 关系型数据库
数据管理DMS操作报错合集之当进行RDS实例的可用区迁移时,提示“缓存清理”是什么意思
数据管理DMS(Data Management Service)是阿里云提供的数据库管理和运维服务,它支持多种数据库类型,包括RDS、PolarDB、MongoDB等。在使用DMS进行数据库操作时,可能会遇到各种报错情况。以下是一些常见的DMS操作报错及其可能的原因与解决措施的合集。
106 3
|
6月前
|
SQL 关系型数据库 数据库
阿里云数据库 RDS SQL Server版实战【性能优化实践、优点探析】
本文探讨了Amazon RDS SQL Server版在云数据库中的优势,包括高可用性、可扩展性、管理便捷、安全性和成本效益。通过多可用区部署和自动备份,RDS确保数据安全和持久性,并支持自动扩展以适应流量波动。可视化管理界面简化了监控和操作,而数据加密和访问控制等功能保障了安全性。此外,弹性计费模式降低了运维成本。实战应用显示,RDS SQL Server版能有效助力企业在促销高峰期稳定系统并保障数据安全。阿里云的RDS SQL Server版还提供了弹性伸缩、自动备份恢复、安全性和高可用性功能,进一步优化性能和成本控制,并与AWS生态系统无缝集成,支持多种开发语言和框架。
416 2
|
2月前
|
关系型数据库 MySQL 网络安全
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
下一篇
无影云桌面