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 ... 
随机推荐
- Ubuntu终端路径和文件夹相互切换
			一. 环境配置 1. 打开终端输入安装命令 sudo apt-get install nautilus-open-terminal 2. 重新加载文件管理器 nautilus -q 3. 重启电脑 s ... 
- 7.golang的字符串 string
			golang 字符串为不可变的量 ,字符串定义要使用双引号 package main import "fmt" func main() { var xx string = 'xxx ... 
- HNUSTOJ-1520 压缩编码
			1520: 压缩编码 时间限制: 1 Sec 内存限制: 2 MB提交: 107 解决: 54[提交][状态][讨论版] 题目描述 某工业监控设备不断发回采样数据.每个数据是一个整数(0到1000 ... 
- 数据分析画图,使用原生sql查询数据
			1.使用工具 https://www.hcharts.cn/ http://echarts.baidu.com/ 2.子表查询 id 创建时间 内容 处理者 1 2017-02-01 11:11 1 ... 
- Mac 切换bash zsh等shell
			现在假设大家都安装了iTerm2,我们先把bash切换成zsh,使用命令行如下: chsh -s /bin/zsh 执行命令后,会让你输入电脑的密码,输入即可.完成后,需要完全退出iTerm2,再次进 ... 
- UIDynamic物理引擎
			iOS开发拓展篇—UIDynamic(简单介绍) 一.简单介绍 1.什么是UIDynamic UIDynamic是从iOS 7开始引入的一种新技术,隶属于UIKit框架 可以认为是一种物理引擎,能模拟 ... 
- Ubuntu 14.04 下的MAC OS X 主题安装
			Ubuntu 14.04 下的MAC OS X 主题安装 安装 MAC OS X 主题会帮助你的 Ubuntu 14.04 看起来更像MAC OS X.在这里我们介绍的Macbuntu安装包包含了GT ... 
- mysql查询每个直播间每个用户最早进入时间和最晚退出时间
			myself_sql = 'select room_id,source_id user_id,min(cast(at as datetime)) joinroom,max(cast(at as dat ... 
- shell安装mysql,连接数据库,创建数据库
			https://blog.csdn.net/yhflyl/article/details/83061126 https://blog.csdn.net/wyl9527/article/details/ ... 
- pandas的settingwithWaring报警
			# 0 读取数据 import pandas as pd df = pd.read_csv("beijing_tianqi_2018.csv") # 换掉温度后面的后缀 df.lo ... 
