暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 查询转换-01 or expansion

IT小Chen 2021-04-14
884

Oracle优化器会根据成本考虑是否进行查询转换,例如考虑是否将谓词的or条件转换为union all,即,执行or expansion例如:

原始SQL:

SELECT *

  FROM employees e, departments d

 WHERE (e.email = 'SSTILES' OR d.department_name = 'Treasury')

   AND e.department_id = d.department_id;

优化器可能会将上面的原始SQL改写成如下SQL

SELECT *

  FROM employees e, departments d

 WHERE e.email = 'SSTILES'

   AND e.department_id = d.department_id

UNION ALL

SELECT *

  FROM employees e, departments d

 WHERE d.department_name = 'Treasury'

   AND e.department_id = d.department_id;

过程如下:

Oracle版本:

SQL> select banner_full from v$version;

查看_no_or_expansion参数,默认关闭,即默认启用了or expansion

SQL> conn as sysdba

SQL> select a.ksppinm name, b.ksppstvl value, a.ksppdesc description

  from x$ksppi a, x$ksppcv b

 where a.indx = b.indx

   and a.ksppinm like '_no_or_expansion';

执行SQL查看执行计划

SQL> conn hr/hr@cjcpdb

SQL> set autotrace on

SQL>

SELECT *

  FROM employees e, departments d

 WHERE (e.email = 'SSTILES' OR d.department_name = 'Treasury')

   AND e.department_id = d.department_id;

实际上SQL执行了or expansion,自动将or转换成union all,例如:

SELECT *

  FROM employees e, departments d

 WHERE e.email = 'SSTILES'

   AND e.department_id = d.department_id

UNION ALL

SELECT *

  FROM employees e, departments d

 WHERE d.department_name = 'Treasury'

   AND e.department_id = d.department_id;

通过10053事件,看下实际情况是否真是将or改写成union all

SQL> conn hr/hr@cjcpdb

SQL> alter session set tracefile_identifier='10053';

SQL> SELECT *12345*/ *

  FROM employees e, departments d

 WHERE (e.email = 'SSTILES' OR d.department_name = 'Treasury')

   AND e.department_id = d.department_id;

SQL> alter session set events '10053 trace name context forever ,level 1';

[root@cjcos01 trace]# pwd

/u01/app/oracle/diag/rdbms/cjcdb/cjcdb/trace

[root@cjcos01 trace]# ls *10053*

cjcdb_ora_22978_10053.trc  cjcdb_ora_22978_10053.trm

如果trace下没有生成10053事件的日志,可能是因为这个sql语句已经解析过,可以改写下SQL文本,例如添加/*12345*/

[root@cjcos01 trace]# vim cjcdb_ora_22978_10053.trc

当前SQL

搜索关键字:Final query after transformations,查看SQL改写情况

通过10053trace可以看到,数据库确实是将or条件改写成了union all,并添加了别名VW_ORE_*,这也就是为什么第一个执行计划里有VW_ORE_*的原因。

查看禁用or expansion后的执行计划

SQL> alter session set "_no_or_expansion"=true;

SELECT *

  FROM employees e, departments d

 WHERE (e.email = 'SSTILES' OR d.department_name = 'Treasury')

   AND e.department_id = d.department_id;

更多数据库相关学习资料,可以查看我的ITPUB博客,网名chenoracle

http://blog.itpub.net/29785807/

文章转载自IT小Chen,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论