oracle 理解执行计划

摘要:
·BUFFERSORT是一个BUFFER,但不是SORT。使用AUTOTRACE查看执行计划的学生经常会问执行计划中的BUFFER SORT是什么意思,为什么要在这里排序?BUFFER是执行计划的关键点,其操作是在内存中存储临时表。要说服持怀疑态度的人,至少有一种方法是查询V$SQL_PLAN_STATISTICS_ALL.PROJECTION字段。STATISTICS_LEVEL设置为ALL,然后执行true sort命令,例如selecthire_date、salaryfromhr.employeesorderbyhire_date,并查看其V$SQL_PLAN_STATISTICS_ALL.PROJECTION字段:SYS@br//scripts˃selectprojectionfrov$sql_ plan_ statistics_all其中sql_ id=andoperation='SORT'选项='ORDERBY';项目----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------“HIRE_DATE”[日期,7],“SALARY”[数字,22]1已选中。列表开头的#键表示返回结果中排序字段的数量。

·BUFFER SORT是BUFFER却不是SORT

用AUTOTRACE查看执行的计划的同学常问到执行计划里的BUFFER SORT是什么意思,这里为什么要排序呢?

BUFFER SORT不是一种排序,而是一种临时表的创建方式。

BUFFER是执行计划想要表达的重点,是其操作: 在内存中存放一张临时表。

SORT修饰BUFFER,表示具体在内存的什么地方存放临时表: 在PGA的SQL工作区里的排序区。

至少有一种方法可以说服对此表示怀疑的人们,就是查询V$SQL_PLAN_STATISTICS_ALL.PROJECTION字段。

将STATISTICS_LEVEL设置为ALL先,然后执行真-排序命令,比如:select hire_date,salary from hr.employees order by hire_date

然后查看其V$SQL_PLAN_STATISTICS_ALL.PROJECTION字段:

SYS@br//scripts> select projection from v$sql_plan_statistics_all where sql_id=(select sql_id from v$sql where sql_text='select hire_date,salary from hr.employees order by hire_date') and operation='SORT' and options='ORDER BY';

PROJECTION
--------------------------------------------------------------------------------------------------------------------------------------------
(#keys=1) "HIRE_DATE"[DATE,7], "SALARY"[NUMBER,22]

1 row selected.

其中开头的#keys表示返回的结果中排序的字段数量。

再执行一句真-排序命令:select hire_date,salary from hr.employees order by salary,hire_date

然后查看其V$SQL_PLAN_STATISTICS_ALL.PROJECTION字段,#keys因该为2:

SYS@br//scripts> select projection from v$sql_plan_statistics_all where sql_id=(select sql_id from v$sql where sql_text='select hire_date,salary from hr.employees order by salary,hire_date') and operation='SORT' and options='ORDER BY';

PROJECTION
--------------------------------------------------------------------------------------------------------------------------------------------
(#keys=2) "SALARY"[NUMBER,22], "HIRE_DATE"[DATE,7]

1 row selected.

看,这回2了吧,北方的同学不要笑,请忍住。

来看看我们萌萌的BUFFER SORT的表现吧~

执行下面这个查询,它使用了所谓的BUFFER SORT:

select ch.channel_class,c.cust_city,sum(s.amount_sold) sales_amount
from sh.sales s,sh.customers c,sh.channels ch
where s.cust_id=c.cust_id and s.channel_id=ch.channel_id and
c.cust_state_province='CA' and
ch.channel_desc='Internet'
group by ch.channel_class,c.cust_city

附上其执行计划,Id为5的Operation是BUFFER SORT:
execution Plan
----------------------------------------------------------
Plan hash value: 3047021169

----------------------------------------------------------------------------------------------------
| Id  | Operation              | Name      | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |           |   133 |  7980 |   902   (2)| 00:00:11 |       |       |
|   1 |  HASH GROUP BY         |           |   133 |  7980 |   902   (2)| 00:00:11 |       |       |
|*  2 |   HASH JOIN            |           | 12456 |   729K|   901   (2)| 00:00:11 |       |       |
|   3 |    MERGE JOIN CARTESIAN|           |   383 | 18001 |   408   (1)| 00:00:05 |       |       |
|*  4 |     TABLE ACCESS FULL  | CHANNELS  |     1 |    21 |     3   (0)| 00:00:01 |       |       |
|   5 |     BUFFER SORT        |           |   383 |  9958 |   405   (1)| 00:00:05 |       |       |
|*  6 |      TABLE ACCESS FULL | CUSTOMERS |   383 |  9958 |   405   (1)| 00:00:05 |       |       |
|   7 |    PARTITION RANGE ALL |           |   918K|    11M|   489   (2)| 00:00:06 |     1 |    28 |
|   8 |     TABLE ACCESS FULL  | SALES     |   918K|    11M|   489   (2)| 00:00:06 |     1 |    28 |
----------------------------------------------------------------------------------------------------

查看其V$SQL_PLAN_STATISTICS_ALL.PROJECTION字段:

SYS@br//scripts> select distinct projection from v$sql_plan_statistics_all where sql_id in (select distinct sql_id from v$sql where sql_text like '%where s.cust_id=c.cust_id and s.channel_id=ch.channel_id and%') and operation='BUFFER' and options='SORT';

PROJECTION
--------------------------------------------------------------------------------------------------------------------------------------------
(#keys=0) "C"."CUST_ID"[NUMBER,22], "C"."CUST_CITY"[VARCHAR2,30]

1 row selected.

结果#keys等于0,是0啊... 0意味着该操作根据0个字段排序,那就是没有排序咯。

同样显示SORT但是不SORT打着左灯向右转的还有著名的SORT AGGREGATE。
·RIGHT SEMI

HASH JOIN RIGHT SEMI是exisit判式的一个特殊操作。HASH JOIN是Oracle优化两个表(其中一个数据表数据量较小,而另一个数据量较大)连接的一种方式。因为在整个查询中,子查询的外部表 business.accintvoucher a (视作左表)与内部表 business.accmainvoucher  (视作右表)实际进行的是连接操作,这不可避免的会产生重复记录。Oracle利用SEMI策略来防 止这一情况,即针对 外部表business.accmainvoucher  a的中每一行,一旦与内部表business.accmainvoucher  中的某条记录 匹配成功,将立即返回。

Oracle官方文档对SEMI这种策略进行了定义。
A semi-join returns rows that match an EXISTS subquery without duplicating rows from the left side of the predicate when multiple rows on the right side satisfy the criteria of the subquery。
也就是说,SEMI连接是exists子查询的一种特殊处理方式,semi join最主要的使用场景就是解决exist in

免责声明:文章转载自《oracle 理解执行计划》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇sed合并多条指令修改文本验证码实现原理下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

centos oracle 数据库备份

#!/bin/bashexport ORACLE_BASE=/home/oracle/app/oracleexport ORACLE_HOME=$ORACLE_BASE/product/11.2.0/dbhome_1export ORACLE_SID=orclexport TNS_ADMIN=$ORACLE_HOME/network/adminexport...

dbms_scheduler介绍

dbms_scheduler介绍 10g引入的这个dbms_scheduler包,替代了之前的dbms_job包,该包功能更强大,可以将job需要的各种资源分开再进行组合。1.program1.1 create_program参数说明:  program_name——程序名称  program_type——程序类型(STORED_PROCEDURE,PL...

Oracle快速测试连接是否成功

  Oracle 客户端建立了TNS连接后,可以快速查看连接是否成功。 1.在cmd中执行命令tnsping orcl(全局数据库名称),即可。以下是命令执行后的示例。   2.如果上一步成功,可以进一步执行数据库相关操作命令。 在cmd中先执行命令:sqlplus system/password orcl,之后就可以输入sql命令了,例...

Oracle表空间知识

Oracle表空间知识 一,创建临时表空间 CREATE temporary TABLESPACE TEMP_PNLREPORT tempfile '/oradata2/ORCL/temp_pnlreport.dbf' SIZE 500m AUTOEXTEND ON next 10m MAXSIZE 2g 二,创建一般表空间 create tablesp...

oracle 内置函数(二)字符函数

主要函数: 大小写转换函数 获取子字符串函数(字符串截取) 获取字符串长度函数 字符串连接函数 去除子字符串函数 字符替换函数 字符串出现次数 字符串按照特定符号拆分多行 一、大小写转换 1、upper:转大写 2、lower:转小写  3、initcap:首字母大写 二、获取子字符串函数(字符串截取) substr(str,beginIndex,...

linux定时重启节约内存

linux服务器上运行的一些程序,比较消耗内存,需要定时重启,进行内存定期释放 0 2 * * * sudo /sbin/reboot && echo $(date) '重启成功' >> ~/reboot_log.log 上面这种写法,日志是不会写入reboot_log.log的 crontab -u root -e 0 2 *...