【Oracle篇】SQL性能优化实战案例(从15秒优化到0.08秒)(第七篇,总共七篇)

💫《博主介绍》:✨又是一天没白过,我是奈斯,DBA一名✨

💫《擅长领域》:✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux,也在扩展大数据方向的知识面✌️

💖💖💖大佬们都喜欢静静的看文章,并且也会默默的点赞收藏加关注💖💖💖

    哈喽哈喽,各位小伙伴!👋博主今天终于将统计信息、优化器、执行计划、Hint、STA系列的最后一篇给肝出来啦!🎉🎉这个系列耗时3个月,此系列是目前博主耗时最长的一个系列😭

    为了让这个系列的每一篇博文都能闪闪发亮,博主可是倾尽了毕生所学(但确实花了不少心思,查阅了多篇官方文档),投入了大量的时间和精力。💪💪 部分博文前前后后改了十遍以上,只为为各位小伙伴提供一份高质量的学习资料!📚📚

    所以嘛,看在博主我这么拼,这么精益求精,无私奉献的份上,小伙伴们是不是该给我来个一键三连呢?🙏🙏 

    关于理论部分博主已经在前六篇文章详细做了介绍和阐述,所以今天这篇博客只讲实战案例,讲通过执行计划对慢SQL进行优化,情也煽够了,那么开始今天的慢SQL优化。还是老规矩为了让大家更容易消化和逐个理解,我将分成七篇文章来进行介绍,以便大家劳逸结合而不至于感觉到阅读枯燥,七篇的内容分别如下:

  • 第一篇:统计信息和动态采样的深度剖析
  • 第二篇:全面理解优化器和SQL语句的解析步骤(含执行计划的详细分析和四种查看方式)
  • 第三篇:SQL执行计划之访问路径(含表级别、B树索引、位图索引、簇表四大类访问路径)
  • 第四篇:SQL执行计划之多表连接(含内连接、外连接、半连接、反连接、笛卡尔连接五种连接方式和嵌套、哈希、排序合并三种连接算法)
  • 第五篇:精细化查询优化:如何有效使用Hint对优化器的执行计划进行干预
  • 第六篇:掌握SQL Tuning Advisor优化工具:从工具使用到SQL优化的全方位指南
  • 第七篇:SQL性能优化实战案例(从15秒优化到0.08秒)(当前篇)

案例开始

生产test用户的查询SQL非常慢,用户没有dba权限,通过autotrace查看执行计划,并进行优化

1)执行查询语句

SYS@orcl1> create user test identified by 123456;SYS@orcl1> grant connect to test;
SYS@orcl1> @?/rdbms/admin/utlxplan.sql 
SYS@orcl1> @?/sqlplus/admin/plustrce.sql   ---生成 plustrace角色
SYS@orcl1> grant plustrace to test;           ---普通用户(非dba用户)需要有plustrace角色才能在sqlplus下使用autotrace。SYS@orcl1> conn test/123456
test@orcl1> 
SELECT a.id,a.name,a.sex,a.region,b.logtime,b.cardid,b.score,c.tel,c.joindate
FROM test_member a, test_sales b, test_m10 c
WHERE a.cardid = b.cardidAND b.cardid=c.cardidAND a.name in ('test1175189','test3077390','test7132935')AND b.cardid like '10%'AND c.joindate > to_date('2010-12-15', 'yyyy-mm-dd')
ORDER BY c.joindate;

多表联合查询test_member、test_sales、test_m10表,结果返回3行消耗了接近16秒,查询时间太长,分析SQL执行计划

            

2)显示这条语句的执行计划和统计信息,分析原因 

test@orcl1> set line 400;
test@orcl1> set autotrace on;
test@orcl1> 
SELECT a.id,a.name,a.sex,a.region,b.logtime,b.cardid,b.score,c.tel,c.joindate
FROM test_member a, test_sales b, test_m10 c
WHERE a.cardid = b.cardidAND b.cardid=c.cardidAND a.name in ('test1175189','test3077390','test7132935')AND b.cardid like '10%'AND c.joindate > to_date('2010-12-15', 'yyyy-mm-dd')
ORDER BY c.joindate;

SQL语句的执行计划和统计信息分析

Execution Plan为执行计划部分:执行计划部分列出了相关SQL语句每步的具体情况和消耗,包括访问路径、扫描情况、扫描行数、使用字节数、使用临时空间字节数,以及每个步骤的成本和时间估计

Execution Plan
---------------------------------------------------------------------------------------------
Plan hash value: 3560787711

Plan hash value:这一行是这一条SQL语句的hash值,oracle对每条语句产生的执行计划放在share pool里面,第一次要经过硬解析,产生hash值。下次再执行该语句时候比较hash值,如果相同就不执行硬解析,执行软解析(检查此sql是否被当前用户使用过,如果是就是软解析soft parse,如果否那就是硬解析。DDL总是硬解析,语句从不重用)

    这条执行计划的执行顺序为:4、5、3、6、2、1、0。如果有不懂执行计划的执行顺序的小伙伴可以参考我之前的博客哦,直通车👉【Oracle篇】全面理解优化器和SQL语句的解析步骤(含执行计划的详细分析和四种查看方式)(第二篇,总共七篇)_oracle如何通过解释计划分析优化sql-CSDN博客👈

----------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  |       Operation	      |       Name	    |   Rows  |   Bytes  |  Cost (%CPU)  |   Time    |
----------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |		             |	     3  |	 264  |  76499   (1)  |  00:15:18  |
|   1 |  SORT ORDER BY	      |		             |	     3  | 	 264  |  76499   (1)  |  00:15:18  |
|*  2 |   HASH JOIN	          |		             |	     3  |	 264  |  76498   (1)  |  00:15:18  |
|*  3 |    HASH JOIN	      |		             |	     3  |	 180  |  75726   (1)  |  00:15:09  |
|*  4 |     TABLE ACCESS FULL  |  TEST_MEMBER     |	     3  | 	 123  |  75296   (1)  |  00:15:04  |
|*  5 |     TABLE ACCESS FULL  |  TEST_SALES      |  10000  |	185K  |	   430   (1)  |  00:00:06  |
|*  6 |    TABLE ACCESS FULL   |  TEST_M10        |  86375  |  2361K  |	   772   (1)  |  00:00:10  |
-----------------------------------------------------------------------------------------------------------------------------------------------------------

Id:内部标识符,这里并不是表示的执行计划的执行顺序,只是用于表示执行计划中的节点顺序。特别注意:有*的标识符表示有谓词信息,也就是说这步操作有where过滤条件或者join连接条件,where过滤条件或者join连接条件对于查询性能最重要,通过谓词信息部分考虑是否可以通过添加或修改索引来提高过滤操作的效率。

Operation:描述了数据库执行的具体操作(访问路径),如“SELECT STATEMENT”,“HASH JOIN”等。在这条SQL中虽然没有通过join连接实现多表关联,但通过oracle的内部机制,将SQL进行了hash join连接。

Name: 通常表示正在执行操作的对象的名称,例如表名或索引名。如果是索引名那么表示使用了索引,如果是表名那么就是用到了全表扫描,也可以通过Operation是不是TABLE ACCESS FULL来确定是不是进行了全表扫描,如果是全备扫描,需要重点关注。

Rows/card:估计的行数。这通常是查询优化器对查询结果的估计。

Bytes:估计的字节数。这通常是查询优化器对查询结果的估计。

TempSpc:估计的临时空间需求(以字节为单位)。这通常用于排序或分组操作。虽然这个SQL使用到了ORDER BY排序,但是因为排序的操作很少就没有使用到临时空间,大排序或者分组操作会显示TempSpc这列

Cost (%CPU):开销。估计的成本和CPU使用百分比。成本是查询优化器用来决定执行顺序的一个度量,它考虑了多种因素,如I/O、CPU使用等。

Time:估计的执行时间(HH:MM:SS),返回的结果仅供参考,计划执行不真实。特别注意:虽然估计的执行时间不真实,但是如果这里的时间明显长,那么就需要重点关注。

       

Predicate Information (identified by operation id)为谓词信息部分:谓词信息部分列出了执行计划部分where过滤条件或者join连接条件的信息,其实也就是where过滤条件或者join连接条件都会在谓词信息中,where过滤条件或者join连接条件对于查询性能最重要,通过谓词信息部分考虑是否可以通过添加或修改索引来提高过滤操作的效率。

    列出了执行计划部分where过滤条件或者join连接条件的信息,一共有两种:access表示使用索引作为过滤条件,那么filter表示没有使用索引作为过滤条件

Predicate Information (identified by operation id):
---------------------------------------------------2 - access("B"."CARDID"="C"."CARDID")                              ---access表示的是使用索引作为过滤条件。B表和C表的CARDID列作为两表的关联条件,但是两表的CARDID列并没有索引,多表关联时,oracle会自动选择合适的连接方式,可能连接方式也是一种优化,不用索引也很快,以后待学习3 - access("A"."CARDID"="B"."CARDID")                              ---access表示的是使用索引作为过滤条件。A表和B表的CARDID列作为两表的关联条件,但是两表的CARDID列并没有索引,多表关联时,oracle会自动选择合适的连接方式,可能连接方式也是一种优化,不用索引也很快,以后待学习4 - filter("A"."NAME"='test1175189' OR "A"."NAME"='test3077390' OR         "A"."NAME"='test7132935')                                   ---filter表示没有使用索引作为过滤条件,这个是内部标识符4的谓词信息,根据执行计划部分,是全表扫描,Time耗时了很久,所以需要对name加索引解决,或者通过STA(SQL Tuning Advisor)进行自动优化5 - filter(TO_CHAR("B"."CARDID") LIKE '10%')                       ---filter表示没有使用索引作为过滤条件,这个是内部标识符5的谓词信息,根据执行计划部分,虽然是全表扫描,但是Time并没有耗时多少6 - filter("C"."JOINDATE">TO_DATE(' 2010-12-15 00:00:00', 'syyyy-mm-ddhh24:mi:ss'))                                               ---filter表示没有使用索引作为过滤条件,这个是内部标识符6的谓词信息,根据执行计划部分,虽然是全表扫描,但是Time并没有耗时多少

  

Statistics为执行计划统计信息部分:

Statistics
----------------------------------------------------------0  recursive calls       ---递归调用。对其它SQL语句的调用的次数,越少越好0  db block gets         ---从buffer cache中读取的block的数据281344  consistent gets   ---计算sql占用的运行内存。从buffer cache中读取undo数据的block的数量,281344 * 8192/1024/1024/1024=2G。277030  physical reads  ---计算sql从磁盘读取的IO。从磁盘读取block的数量,如果是全盘扫描那么就是表的实际大小,277030 * 8192/1024/1024/ 1024=2G0  redo size                               ---生成的redo大小。Select不生成redo数据,所以为0  1324  bytes sent via SQL*Net to client        ---服务器到客户端的字节总数519  bytes received via SQL*Net from client  ---客户机接受的字节数2  SQL*Net roundtrips to/from client       ---客户机到服务器之间发生的sql*net 次数1  sorts (memory)                          ---在内存执行的排序量0  sorts (disk)                            ---在磁盘上执行的排序量3  rows processed                          ---影响数据的行数。就是结果返回的行数

      

3)对SQL语句进行分析,创建合适的索引

通过Execution Plan分析如下:

(1)执行计划中,耗时的部分都在对TEST_MEMBER进行全表扫描(TABLE ACCESS FULL),TEST_SALES和TEST_M10也进行了全表扫描(TABLE ACCESS FULL),但是耗时不长,所以TEST_SALES和TEST_M10可以不创建索引进行优化,TEST_MEMBER必须通过给出谓词进行进行创建索引优化

通过Predicate Information (identified by operation id)分析如下:

(1)filter表示没有使用索引作为过滤条件,那么结合Execution Plan部分进行分析,TEST_MEMBER进行的全表扫描(TABLE ACCESS FULL)对应的就是内部标识符4的谓词信息,所以对TEST_MEMBER的name列加上索引

                      

创建索引:

TEST@orcl1> create index idx_test_member_name on test_member(name);  

          

4)再次执行SQL语句,并查看执行计划

test@orcl1> 
SELECT a.id,a.name,a.sex,a.region,b.logtime,b.cardid,b.score,c.tel,c.joindate
FROM test_member a, test_sales b, test_m10 c
WHERE a.cardid = b.cardidAND b.cardid=c.cardidAND a.name in ('test1175189','test3077390','test7132935')AND b.cardid like '10%'AND c.joindate > to_date('2010-12-15', 'yyyy-mm-dd')
ORDER BY c.joindate;

通过创建索引优化,查询时间降到了0.08秒

               

Execution Plan部分:test_member表不再进行全表扫描,而是使用到了IDX_TEST_MEMBER_NAME索引,进行了索引范围扫描(index range scan)

Predicate Information (identified by operation id)部分:access表示的是使用索引作为过滤条件。索引范围扫描(index range scan)对应的就是内部标识符4的谓词信息,test_member的name使用了索引


    慢SQL优化圆满结束,在实际生产环境执行的SQL都在几百行,甚至上千行,要比这篇博客的SQL要复杂的多,但只要掌握了优化技巧和优化原理,即使再复杂的SQL通过多次实践也会手到擒来的,那么这篇文章就圆满结束,这个系列到这里也画上了圆满的句号。 一个人可以走的很快,一群人才能走的更远 ,也希望各位集帅多提宝贵建议,让这个系列成为全网关于统计信息、优化器、执行计划、Hint、STA相关内容最全的学习资料~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/61400.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

神经网络入门实战:(一)神经网络解决的两种问题,以及AI、机器学习、深度学习三者之间的逻辑关系

AI、机器学习、深度学习三者之间的逻辑关系: 两种问题 (1)回归问题 回归问题是指预测一个或多个连续值的任务。这些连续值可以是任意实数,比如价格、温度、分数等。 回归问题的目标通常是 找到一个函数 ,该函数可以…

深入解析TK技术下视频音频不同步的成因与解决方案

随着互联网和数字视频技术的飞速发展,音视频同步问题逐渐成为网络视频播放、直播、编辑等过程中不可忽视的技术难题。尤其是在采用TK(Transmission Keying)技术进行视频传输时,由于其特殊的时序同步要求,音视频不同步现…

【Chatgpt】如何通过分层Prompt生成更加细致的图文内容

如何通过分层Prompt生成更加细致的图文内容 利用ChatGPT和类似的生成式AI模型,通过分层Prompt设计可以生成更具层次感和细节的图文内容。分层Prompt的核心在于将需求分解成多层次的指令,从宏观到微观逐步细化,最终形成高质量的内容输出。 一…

豆包MarsCode算法题:最小周长巧克力板组合

问题描述 思路分析 这道题可以抽象为一个最优化问题: 问题分析 每个正方形的面积为 k ,对应的边长为 k ,周长为 4k 。给定整数 n ,我们需要找到若干正方形,使得它们的面积之和恰好等于 n: 同时尽量最小…

解析与修复vcruntime140_1.dll问题,总结四种vcruntime140_1.dll解决方法

在使用Windows系统的过程中,不少用户可能会遇到与vcruntime140_1.dll相关的问题。这个看似神秘的文件,其实在很多软件的运行中扮演着至关重要的角色。今天的这篇文章将教大家四种vcruntime140_1.dll解决方法。 一、vcruntime140_1.dll文件分析 &#xf…

WebGL进阶(九)光线

理论基础: 点光源 符合向量定义,末减初。 平行光 环境光 效果: 点光源 平行光 环境光 源码: 点光源 平行光 环境光 复盘:

【Amazon】亚马逊云科技Amazon DynamoDB 实践Amazon DynamoDB

Amazon DynamoDB 是一种完全托管的 NoSQL 数据库服务,专为高性能和可扩展性设计,特别适合需要快速响应和高吞吐量的应用场景,如移动应用、游戏、物联网和实时分析等。 工作原理 Amazon DynamoDB 在任何规模下响应时间一律达毫秒级&#xff…

【AIGC】ChatGPT提示词Prompt解析:拒绝的艺术:如何优雅地说“不“

引言 在人际交往的复杂网络中,学会优雅地拒绝是一种至关重要的社交智慧。很多人往往因为害怕伤害他人的感受,而选择敷衍、拖延或不置可否。 然而,真正的智慧在于如何用尊重和同理心传达"不"的信息。 本文将深入探讨优雅拒绝的艺术,帮助你在维护自身边界的同时,…

Java项目实战II基于微信小程序的农场驿站平台(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 随着移动互…

SpringBoot(三十三)SpringBoot集成Spring boot actuator程序监控器

Springboot集成actuator还是比较简单的。 但是,我们需要先了解一下什么是actuactor呢? 如标题所示,actuator是程序监控器。 提供了生产级别的功能,比如健康检查,审计,指标收集,HTTP 跟踪等,帮助我们监控和管理Spring Boot 应用。 这个模块是一个采集应用内部信息暴露给…

各类主流MQ使用场景对比说明

先上对比纲要,各MQ的详细说明可以继续看后面的文章 1. Apache Kafka 优势: 高吞吐量和低延迟。支持分布式架构,具有很好的伸缩性。容错性强,即使单个节点失败也不会影响整体服务。 劣势: 复杂度较高,配…

KMP算法(java)next数组和next函数修正值

BF算法 最简单直观的模式匹配算法是BF(Brute-Force)算法。 模式匹配不一定是从主串的第一个位置开始,可以指定主串中查找的起始位置pos。如果采用字符串顺序存储结构,可以写出不依赖于其他串操作的匹配算法。 最坏情况下的平均时间复杂度是O(nxm)。 …

matlab基础例题

1. MATLAB 命令窗口中可用____命令清除工作区中的变量;用____命令清除命令窗口中的内容。 2. MATLAB 中的运算包括________________。 3. MATLAB 中的 M 文件有_____________。 4. MATLAB 中的程序控制结构包括___________. 5.已知矩阵 A [1 2 3;4 5 6;7 8 9],A…

支付宝租赁小程序的优势与应用前景分析

内容概要 在这个快节奏的时代,租赁服务越来越成为大家生活中的一部分。而支付宝租赁小程序正是这个大潮流中的一颗璀璨明珠。通过简单易用的界面和强大的功能,这个小程序不仅让用户在租赁过程中获得了前所未有的便利,也为商家提供了新的商业…

Elasticsearch 中的热点以及如何使用 AutoOps 解决它们

作者:来自 Elastic Sachin Frayne 探索 Elasticsearch 中的热点以及如何使用 AutoOps 解决它。 Elasticsearch 集群中出现热点的方式有很多种。有些我们可以控制,比如吵闹的邻居,有些我们控制得较差,比如 Elasticsearch 中的分片分…

【H2O2|全栈】JS进阶知识(七)ES6(3)

目录 前言 开篇语 准备工作 递归 概念 形式 优缺点 案例 数组求和 斐波那契数列 递归查找数据 柯里化 概念 形式 什么时候使用柯里化? 多维数组扁平化 多维数组 扁平化 利用flat() 与字符串相互转化 与JSON字符串相互转化 some(),…

字符数组和字符指针

为什么C程序里面不能对字符数组进行重新赋值而可以在控制台进行输入赋值? 在C语言中,字符数组(char array)和字符指针(char pointer)是两种不同的数据类型,它们在内存中的存储方式和使用方式有…

【架构】主流企业架构Zachman、ToGAF、FEA、DoDAF介绍

文章目录 前言一、Zachman架构二、ToGAF架构三、FEA架构四、DoDAF 前言 企业架构(Enterprise Architecture,EA)是指企业在信息技术和业务流程方面的整体设计和规划。 最近接触到“企业架构”这个概念,转念一想必定和我们软件架构…

迷宫题解 题目ID:8015

题目描述 时间限制: 1s 空间限制:32M 题目描述: 给定一个N∗M 方格的迷宫,每个方格最多经过一次,且迷宫里有 T 处障碍,障碍处不可通过。 在迷宫中有上下左右四种移动方式,每次只能移动一个方…

Kafka Stream实战教程

Kafka Stream实战教程 1. Kafka Streams 基础入门 1.1 什么是 Kafka Streams Kafka Streams 是 Kafka 生态中用于 处理实时流数据 的一款轻量级流处理库。它利用 Kafka 作为数据来源和数据输出,可以让开发者轻松地对实时数据进行处理,比如计数、聚合、…