SQL优化—nested loop优化
跑批时间段22:00-23:00,生成AWR报告
分析sql:SQL_ID='5hfw4smzs2pqw'
执行计划:
SQL> select * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('5hfw4smzs2pqw',NULL,'ALL'));
SQL_ID 5hfw4smzs2pqw, child number 0 ------------------------------------- SELECT a.SEQ_NO,a.ACCTNO,a.POST_TXN_CD,b.POST_METHOD_CD,b.AMT_TYPE,a.BIL L_AMT,a.POST_DATE,a.EXPLAIN FROM T_EMPLOYY_A a INNER JOIN T_EMPLOYY_B b ON a.POST_TXN_CD=b.POST_TXN_CD AND a.POST_DATE=:1 AND a.ACCTNO=:2 AND POST_STATUS_CD='' Plan hash value: 3635671702 -------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 5248 (100)| | | 1 | NESTED LOOPS | | 1 | 71 | 5248 (1)| 00:00:01 | | 2 | NESTED LOOPS | | 1 | 71 | 5248 (1)| 00:00:01 | |* 3 | TABLE ACCESS FULL | T_EMPLOYY_A | 1 | 61 | 5247 (1)| 00:00:01 | |* 4 | INDEX UNIQUE SCAN | PK_T_EMPLOYY_B | 1 | | 0 (0)| | | 5 | TABLE ACCESS BY INDEX ROWID| T_EMPLOYY_B | 1 | 10 | 1 (0)| 00:00:01 | -------------------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$58A6D7F6 3 - SEL$58A6D7F6 / A@SEL$1 4 - SEL$58A6D7F6 / B@SEL$1 5 - SEL$58A6D7F6 / B@SEL$1 Predicate Information (identified by operation id): --------------------------------------------------- 3 - filter(("A"."ACCTNO"=:2 AND "A"."POST_DATE"=:1 AND "POST_STATUS_CD"='')) 4 - access("A"."POST_TXN_CD"="B"."POST_TXN_CD") Column Projection Information (identified by operation id): ----------------------------------------------------------- 1 - "A"."SEQ_NO"[NUMBER,22], "A"."ACCTNO"[VARCHAR2,40], "A"."POST_DATE"[CHARACTER,8], "A"."POST_TXN_CD"[NUMBER,22], "A"."BILL_AMT"[NUMBER,22], "A"."EXPLAIN"[VARCHAR2,200], "B"."POST_METHOD_CD"[NUMBER,22], "B"."AMT_TYPE"[CHARACTER,2] 2 - "A"."SEQ_NO"[NUMBER,22], "A"."ACCTNO"[VARCHAR2,40], "A"."POST_DATE"[CHARACTER,8], "A"."POST_TXN_CD"[NUMBER,22], "A"."BILL_AMT"[NUMBER,22], "A"."EXPLAIN"[VARCHAR2,200], "B".ROWID[ROWID,10] 3 - "A"."SEQ_NO"[NUMBER,22], "A"."ACCTNO"[VARCHAR2,40], "A"."POST_DATE"[CHARACTER,8], "A"."POST_TXN_CD"[NUMBER,22], "A"."BILL_AMT"[NUMBER,22], "A"."EXPLAIN"[VARCHAR2,200] 4 - "B".ROWID[ROWID,10] 5 - "B"."POST_METHOD_CD"[NUMBER,22], "B"."AMT_TYPE"[CHARACTER,2] Note ----- - this is an adaptive plan
执行计划
分析:
执行计划:3-->2-->4-->5-->1-->0
第一层循环:根据POST_DATE=:1,ACCTNO=:2,POST_STATUS_CD='0'嵌套循环,全表扫描驱动表T_EMPLOYY_A;
第二层循环:根据a.POST_TXN_CD=b.POST_TXN_CD,嵌套循环,根据索引PK_T_EMPLOYY_B,得到rowid,访问表T_EMPLOYY_B
索引信息:
SQL> select TABLE_NAME,INDEX_NAME,COLUMN_NAME from dba_ind_columns where TABLE_NAME='T_EMPLOYY_A';
TABLE_NAME INDEX_NAME COLUMN_NAME
-------------------- -------------------- ------------------------------
T_EMPLOYY_A PK_T_EMPLOYY_A SEQ_NO
SQL> select TABLE_NAME,INDEX_NAME,COLUMN_NAME from dba_ind_columns where TABLE_NAME='T_EMPLOYY_B';
TABLE_NAME INDEX_NAME COLUMN_NAME
-------------------- -------------------- ------------------------------
T_EMPLOYY_B PK_T_EMPLOYY_B POST_TXN_CD
表T_EMPLOYY_A条件列、连接条件字段没有索引
表的总行数
SQL> select count(*) from SCOTT.T_EMPLOYY_A;
COUNT(*)
----------
2029447
SQL> select count(*) from SCOTT.T_EMPLOYY_B;
COUNT(*)
----------
52
连接列的匹配情况:
SQL> select count(distinct(POST_TXN_CD)) from SCOTT.T_EMPLOYY_A;
COUNT(DISTINCT(POST_TXN_CD))
----------------------------
26
SQL> select count(distinct(POST_TXN_CD)) from SCOTT.T_EMPLOYY_B;
COUNT(DISTINCT(POST_TXN_CD))
----------------------------
52
ACCTNO列在T_EMPLOYY_A表的筛选性
SQL> select count(distinct(ACCTNO)) from SCOTT.T_EMPLOYY_A;
COUNT(DISTINCT(ACCTNO))
-----------------------
225427
POST_DATE列在T_EMPLOYY_A表的筛选性
SQL> select count(distinct(POST_DATE)) from SCOTT.T_EMPLOYY_A;
COUNT(DISTINCT(POST_DATE))
--------------------------
736
SQL> select count(*) from ( select distinct ACCTNO,POST_DATE from SCOTT.T_EMPLOYY_A);
COUNT(*)
----------
1690282
优化建议:1:在表T_EMPLOYY_A的ACCTNO, POST_DATE列创建联合索引
2:利用hind,修改驱动表为T_EMPLOYY_B.但是需要修改SQL语句,需上线调整,所以不使用。
ACCTNO筛选性强,放在联合索引列的前面
创建联合索引
SQL> create index IDX_ACCTNO_POST_DATE on SCOTT.T_EMPLOYY_A (ACCTNO, POST_DATE) tablespace SCOTT_IDX01
SQL> select * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('5hfw4smzs2pqw',NULL,'ALL'));
SQL_ID 5hfw4smzs2pqw, child number 0 ------------------------------------- SELECT a.SEQ_NO,a.ACCTNO,a.POST_TXN_CD,b.POST_METHOD_CD,b.AMT_TYPE,a.BIL L_AMT,a.POST_DATE,a.EXPLAIN FROM T_EMPLOYY_A a INNER JOIN T_EMPLOYY_B b ON a.POST_TXN_CD=b.POST_TXN_CD AND a.POST_DATE=:1 AND a.ACCTNO=:2 AND POST_STATUS_CD='' Plan hash value: 1730680787 -------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 5 (100)| | | 1 | NESTED LOOPS | | 1 | 71 | 5 (0)| 00:00:01 | | 2 | NESTED LOOPS | | 1 | 71 | 5 (0)| 00:00:01 | |* 3 | TABLE ACCESS BY INDEX ROWID BATCHED| T_EMPLOYY_A | 1 | 61 | 4 (0)| 00:00:01 | |* 4 | INDEX RANGE SCAN | IDX_ACCTNO_POST_DATE | 1 | | 3 (0)| 00:00:01 | |* 5 | INDEX UNIQUE SCAN | PK_T_EMPLOYY_B | 1 | | 0 (0)| | | 6 | TABLE ACCESS BY INDEX ROWID | T_EMPLOYY_B | 1 | 10 | 1 (0)| 00:00:01 | -------------------------------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$58A6D7F6 3 - SEL$58A6D7F6 / A@SEL$1 4 - SEL$58A6D7F6 / A@SEL$1 5 - SEL$58A6D7F6 / B@SEL$1 6 - SEL$58A6D7F6 / B@SEL$1 Predicate Information (identified by operation id): --------------------------------------------------- 3 - filter("POST_STATUS_CD"='') 4 - access("A"."ACCTNO"=:2 AND "A"."POST_DATE"=:1) 5 - access("A"."POST_TXN_CD"="B"."POST_TXN_CD") Column Projection Information (identified by operation id): ----------------------------------------------------------- 1 - "A"."SEQ_NO"[NUMBER,22], "A"."ACCTNO"[VARCHAR2,40], "A"."POST_DATE"[CHARACTER,8], "A"."POST_TXN_CD"[NUMBER,22], "A"."BILL_AMT"[NUMBER,22], "A"."EXPLAIN"[VARCHAR2,200], "B"."POST_METHOD_CD"[NUMBER,22], "B"."AMT_TYPE"[CHARACTER,2] 2 - "A"."SEQ_NO"[NUMBER,22], "A"."ACCTNO"[VARCHAR2,40], "A"."POST_DATE"[CHARACTER,8], "A"."POST_TXN_CD"[NUMBER,22], "A"."BILL_AMT"[NUMBER,22], "A"."EXPLAIN"[VARCHAR2,200], "B".ROWID[ROWID,10] 3 - "A"."SEQ_NO"[NUMBER,22], "A"."ACCTNO"[VARCHAR2,40], "A"."POST_DATE"[CHARACTER,8], "A"."POST_TXN_CD"[NUMBER,22], "A"."BILL_AMT"[NUMBER,22], "A"."EXPLAIN"[VARCHAR2,200] 4 - "A".ROWID[ROWID,10], "A"."ACCTNO"[VARCHAR2,40], "A"."POST_DATE"[CHARACTER,8] 5 - "B".ROWID[ROWID,10] 6 - "B"."POST_METHOD_CD"[NUMBER,22], "B"."AMT_TYPE"[CHARACTER,2] Note ----- - this is an adaptive plan
优化后的执行计划
两天跑批时间段22:00-23:00的性能对比
经优化后,数据库逻辑读下降,CPU负载下降
20180808逻辑读:
20180809逻辑读:
SQL优化—nested loop优化的更多相关文章
- SQL Server nested loop join 效率试验
从很多网页上都看到,SQL Server有三种Join的算法, nested loop join, merge join, hash join. 其中最常用的就是nested loop join. 在 ...
- oracle 表连接 - nested loop 嵌套循环连接
一. nested loop 原理 nested loop 连接(循环嵌套连接)指的是两个表连接时, 通过两层嵌套循环来进行依次的匹配, 最后得到返回结果集的表连接方法. 假如下面的 sql 语句中表 ...
- Sql优化(一) Merge Join vs. Hash Join vs. Nested Loop
原创文章,首发自本人个人博客站点,转载请务必注明出自http://www.jasongj.com Nested Loop,Hash Join,Merge Join介绍 Nested Loop: 对于被 ...
- 1122MySQL性能优化之 Nested Loop Join和Block Nested-Loop Join(BNL)
转自http://blog.itpub.net/22664653/viewspace-1692317/ 一 介绍 相信许多开发/DBA在使用MySQL的过程中,对于MySQL处理多表关联的方式或者说 ...
- 如何在不改SQL的情况下优化数据库
主题简介 在数据库运维中我们会遇到各种各样的问题,这些问题的根源可能很明显,也可能被某种表象掩盖而使我们认不清.所以运维面临的两大问题就是,第一我们没有看清本质,第二应用不允许修改.那么我们如何解决这 ...
- 【转】使用SQL Tuning Advisor STA优化SQL
SQL优化器(SQL Tuning Advisor STA)是Oracle10g中推出的帮助DBA优化工具,它的特点是简单.智能,DBA值需要调用函数就可以给出一个性能很差的语句的优化结果.下面介绍一 ...
- 【转】MySQL批量SQL插入各种性能优化
原文:http://mp.weixin.qq.com/s?__biz=MzA5MzY4NTQwMA==&mid=403182899&idx=1&sn=74edf28b0bd29 ...
- SQL Server数据库性能优化之SQL语句篇【转】
SQL Server数据库性能优化之SQL语句篇http://www.blogjava.net/allen-zhe/archive/2010/07/23/326927.html 近期项目需要, 做了一 ...
- SQL SERVER 查询性能优化——分析事务与锁(五)
SQL SERVER 查询性能优化——分析事务与锁(一) SQL SERVER 查询性能优化——分析事务与锁(二) SQL SERVER 查询性能优化——分析事务与锁(三) 上接SQL SERVER ...
随机推荐
- python学习-第四天补充-面向对象
python学习-第四天补充-面向对象 python 私有 --name mangling(名字修改.名字) 在命名时,通过使用两个下划线作为开头,可以使得这个变量或者函数编程私有的,但是这个其实的p ...
- C++代码审查
C++代码审查 1. 目的与要求 寻找结对编程伙伴,并练习结对编程: 对同伴的作品进行代码复审,设计审查表并填写: 评价同伴的代码,介绍同伴的优缺点. 2. 复审代码 小伙伴李宏达的项目代码与博客地址 ...
- [HDU 3712] Fiolki (带边权并查集+启发式合并)
[HDU 3712] Fiolki (带边权并查集+启发式合并) 题面 化学家吉丽想要配置一种神奇的药水来拯救世界. 吉丽有n种不同的液体物质,和n个药瓶(均从1到n编号).初始时,第i个瓶内装着g[ ...
- Y7000 安装ubuntu16.04.6 的tips :禁用nouveau 、Wifi 问题 、nvidia 驱动安装
由于最近要跑DeepLearning 所以在自己的Y7000上装一个Ubuntu ,自己碰了好多壁 写下来以防止自己忘掉以便后续再用! 配置:i7-8750H +GeForce GTX 1050Ti ...
- 前端UI库推荐(pc和移动)
此推荐个人喜好,不喜勿喷. 1. pc 端 elementUI (生态强大,样式生硬) iview (推荐,组件丰富) bootStrap layUI easyUi 2. 移动端 mintUI ant ...
- Vue 中如何定义全局的变量和常量
Vue 中如何定义全局的变量和常量 我想要定义一个变量, 在项目的任何地方都可以访问到, 不需要每一次使用的时候, 都引入. 尝试1:创建 global.js 并且在其中定义 let a = 10 ...
- Netty入门搭建
什么是Netty Netty 是一个基于 JAVA NIO 类库的异步通信框架,它的架构特点是:异步非阻塞.基于事件驱动.高性能.高可靠性和高可定制性. 为什么选择netty而不是使用NIO 1.使用 ...
- centOS7 通过nmtui和nmcli图形配置网络服务
一.通过nmtui配置网络参数 Linux系统配置网络参数的方式有很多种,其中最简单最直接的方式就是直接修改网卡配置文件,但这种方式也很容易出错,比如说IPADDR.NETMASK.GATEWAY等参 ...
- Django【第9篇】:Django之用户认证auth模块
用户认证--------------auth模块 一.auth模块 from django.contrib import auth 1 .authenticate() :验证用户输入的用户名和密码 ...
- 【SaltStack官方版】—— states教程, part 3 - 定义,包括,延伸
STATES TUTORIAL, PART 3 - TEMPLATING, INCLUDES, EXTENDS 本教程建立在第1部分和第2部分涵盖的主题上.建议您从此开始.这章教程我们将讨论更多 s ...