从上述显示内容中可以看出,Id=3的执行步骤“BUFFER SORT”所对应的“#keys”的值为0,说明该SQL在执行“BUFFER SORT”时确实没有排序,排序的数量为0。
这就验证了我们之前提到的观点:统计信息中sorts(memory)和sorts(disk)的值对于BUFFER SORT而言是不准的,Oracle在执行BUFFER SORT时可能不需要排序。
6. UNION/UNION ALL
UNION/UNION ALL表示对两个结果集进行合并,如果它们出现在执行计划中也表示相同的含义。
UNION和UNION ALL的区别是:UNION ALL仅仅是简单地将两个结果集合并,并不做任何额外的处理;而UNION除了将两个结果集简单合并之外,还会对合并后的结果集做排序和去重,即UNION相当于先做UNION ALL,然后再对UNION ALL之后的结果集做SORT UNIQUE
看一个实例:
select empno,ename from scott.emp union all select empno,ename from emp_temp;
EMPNO ENAME
---------- ------------------------------
7369 SMITH
......
7934 MILLER
27 rows selected.
从上述显示内容中可以看出,现在该SQL的执行计划走的是对表EMP和EMP_TEMP全表扫描后的结果集的UNION ALL,UNION ALL在执行计划中对应的关键字就是UNION-ALL。表EMP有13条记录,表EMP_TEMP有12条记录,UNION ALL合并后的结果集总是25。
把UNION ALL改为UNION:
zx@MYDB>select empno,ename from scott.emp union select empno,ename from emp_temp;
EMPNO ENAME
---------- ------------------------------
7369 SMITH
......
7934 MILLER
14 rows selected.
从上述显示内容可以看出,现在该SQL的执行计划走的是对EMP和EMP_TEMP全表扫描的结果集的UNION,UNION在执行计划中对应的关键字就是"UNION-ALL"和"SORT UNIQUE",即表示UNION相当于在UNION ALL的基础上做排序和去重。表EMP_TEMP的数据全部来源于表EMP,所以这里UNION操作返回结果集的复数就是表EMP的行数14。
7. CONCAT
CONCAT就是IN-List扩展(IN-List Expansion)或OR扩展(OR Expansion),IN-List扩展/OR扩展在执行计划中对应的关键字是“CONCATENATION”,使用Hint来强制让Oracle走IN-List扩展/OR扩展。
看一下实例:
zx@MYDB>select empno,ename from scott.emp where empno in (7654,7698,7782);
EMPNO ENAME
---------- ------------------------------
7654 MARTIN
7698 BLAKE
7782 CLARK
从上述显示内容可以看出,现在该SQL的执行计划走的是对表EMP和主键索引PK_EMP的IN-List迭代。
使用Hint让Oracle强制走IN-List扩展
zx@MYDB>select /*+ USE_CONCAT */empno,ename from scott.emp where empno in (7654,7698,7782);
EMPNO ENAME
---------- ------------------------------
7654 MARTIN
7698 BLAKE
7782 CLARK