oracle对于子查询的支持做的很好,oracle optimizer会对inline view进行query transfomation,即视图合并,不过也经常带来意想不到的问题。
下面是一个inline view的merge的例子:

1,  创建临时表

 create table test1 as select * from dba_objects;
create table test2 as select * from dba_objects;

2,  以下查询语句

select *
from test1 t1,
(select owner,
max(object_id) maxo,
min(object_id) mino,
avg(object_id) avgo
from test2
group by owner) t2
where t1.owner = t2.owner
and t1.object_id > t2.avgo;

3,  下面看下语句的执行计划:
  

--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 90420 | 18M| | 1540 (1)| 00:00:19 |
|* 1 | FILTER | | | | | | |
| 2 | HASH GROUP BY | | 90420 | 18M| | 1540 (1)| 00:00:19 |
|* 3 | HASH JOIN | | 90420 | 18M| 3712K| 1535 (1)| 00:00:19 |
| 4 | TABLE ACCESS FULL| TEST2 | 90420 | 2649K| | 246 (1)| 00:00:03 |
| 5 | TABLE ACCESS FULL| TEST1 | 90420 | 16M| | 247 (2)| 00:00:03 |
-------------------------------------------------------------------------------------- Predicate Information (identified by operation id):
--------------------------------------------------- 1 - filter("T1"."OBJECT_ID">SUM("OBJECT_ID")/COUNT("OBJECT_ID"))
3 - access("T1"."OWNER"="OWNER")

这里,oracle对inline view进行了视图合并,其执行过程是:

  1. 对test2,test1进行hash join。
  2. 对结果进行group by分组
  3. 然后过滤object_id大于均值的记录

看下其执行的情况:

26864 rows selected.
Elapsed: 00:11:53.64
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
2172 consistent gets
1081 physical reads
0 redo size
2304647 bytes sent via SQL*Net to client
20182 bytes received via SQL*Net from client
1792 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
26864 rows processed

两个表的记录数:66957。结果集数:26864。
而整体的运行时间接近12分钟。
下面调整一下查询的执行计划,使用no_merge hint使用优化器不进行查询装换,对inline view不进行合并:

  

select /*+ no_merge(t2)*/*
from test1 t1,
(select owner,
max(object_id) maxo,
min(object_id) mino,
avg(object_id) avgo
from test2
group by owner) t2
where t1.owner = t2.owner
and t1.object_id > t2.avgo; 26864 rows selected.
Elapsed: 00:00:01.47
Execution Plan
----------------------------------------------------------
Plan hash value: 1122024653
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4521 | 1028K| | 1600 (1)| 00:00:20 |
|* 1 | HASH JOIN | | 4521 | 1028K| 6008K| 1600 (1)| 00:00:20 |
| 2 | VIEW | | 90420 | 4944K| | 251 (3)| 00:00:04 |
| 3 | HASH GROUP BY | | 90420 | 2649K| | 251 (3)| 00:00:04 |
| 4 | TABLE ACCESS FULL| TEST2 | 90420 | 2649K| | 246 (1)| 00:00:03 |
| 5 | TABLE ACCESS FULL | TEST1 | 90420 | 15M| | 247 (2)| 00:00:03 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("T1"."OWNER"="T2"."OWNER")
filter("T1"."OBJECT_ID">"T2"."AVGO")
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
3934 consistent gets
0 physical reads
0 redo size
1602672 bytes sent via SQL*Net to client
20182 bytes received via SQL*Net from client
1792 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
26864 rows processed

使用no_merge hint,其执行过程是:先对test2先进行group by分组,然后对中间结果集进行hash驱动来join。
对比不同的执行计划,两个执行的时间却相差甚远。

现在打开10046 event,来看一下执行的具体花费的时间和计算的cost:

  

********************************************************************************
select /*+ no_merge(t2)*/*
from test1 t1,
(select owner,
max(object_id) maxo,
min(object_id) mino,
avg(object_id) avgo
from test2
group by owner) t2
where t1.owner = t2.owner
and t1.object_id > t2.avgo
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1792 0.70 0.68 0 3934 0 26864
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 1794 0.70 0.68 0 3934 0 26864
Rows Row Source Operation
------- ---------------------------------------------------
26864 HASH JOIN (cr=3934 pr=0 pw=0 time=569062 us)
121 VIEW (cr=1086 pr=0 pw=0 time=216305 us)
121 HASH GROUP BY (cr=1086 pr=0 pw=0 time=216052 us)
66953 TABLE ACCESS FULL TEST2 (cr=1086 pr=0 pw=0 time=67093 us)
66957 TABLE ACCESS FULL TEST1 (cr=2848 pr=0 pw=0 time=69776 us)
Rows Execution Plan
------- ---------------------------------------------------
0 SELECT STATEMENT MODE: ALL_ROWS
26864 HASH JOIN
121 VIEW
121 HASH (GROUP BY)
66953 TABLE ACCESS (FULL) OF 'TEST2' (TABLE)
66957 TABLE ACCESS (FULL) OF 'TEST1' (TABLE)
********************************************************************************

下面看另外一个merge后的执行情况:

********************************************************************************
select *
from test1 t1,
(select owner,
max(object_id) maxo,
min(object_id) mino,
avg(object_id) avgo
from test2
group by owner) t2
where t1.owner = t2.owner
and t1.object_id > t2.avgo call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1792 530.60 518.52 0 2172 0 26864
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 1794 530.60 518.52 0 2172 0 26864
Rows Row Source Operation
------- ---------------------------------------------------
26864 FILTER (cr=2172 pr=0 pw=0 time=518383093 us)
66957 HASH GROUP BY (cr=2172 pr=0 pw=0 time=518245046 us)
147500423 HASH JOIN (cr=2172 pr=0 pw=0 time=147797490 us)
66953 TABLE ACCESS FULL TEST2 (cr=1086 pr=0 pw=0 time=67029 us)
66957 TABLE ACCESS FULL TEST1 (cr=1086 pr=0 pw=0 time=67029 us) Rows Execution Plan
------- ---------------------------------------------------
0 SELECT STATEMENT MODE: ALL_ROWS
26864 FILTER
66957 HASH (GROUP BY)
147500423 HASH JOIN
66953 TABLE ACCESS (FULL) OF 'TEST2' (TABLE)
66957 TABLE ACCESS (FULL) OF 'TEST1' (TABLE)
********************************************************************************

可以很明显的看出,时间花费在什么地方了。在进行hash group by和filter的过程中花费了大量的时间。
因为test1和test2进行hash join的中间结果有147,500,423条。

  

总结:
无论是inline view的merge还是其它的可选执行计划,最优的那个访问路径一定是具备了以下的条件:

  1. 优先对查询应用过滤性条件,尽可能多的减少中间结果集。
  2. 尽可能的只扫描期望得到的那一部分数据,减少不必要的开销。

oracle查询转换_view merge的更多相关文章

  1. oracle查询转换_inlist转换

    oracle的optimizer会对一些sql语句进行查询转换,比如: 合并视图 子查询非嵌套化 inlist转换 下面讲讲遇到的in list转化优化的案例: create table test( ...

  2. oracle里的查询转换

    oracle里的查询转换的作用 Oracle里的查询转换,有称为查询改写,指oracle在执行目标sql时可能会做等价改写,目的是为了更高效的执行目标sql 在10g及其以后的版本中,oracle会对 ...

  3. 45 个非常有用的 Oracle 查询语句

    ​ 这里我们介绍的是 40+ 个非常有用的 Oracle 查询语句,主要涵盖了日期操作,获取服务器信息,获取执行状态,计算数据库大小等等方面的查询.这些是所有 Oracle 开发者都必备的技能,所以快 ...

  4. 40多个非常有用的Oracle 查询语句

    给大家介绍是40多个非常有用的Oracle 查询语句,主要涵盖了日期操作,获取服务器信息,获取执行状态,计算数据库大小等等方面的查询.这些是所有Oracle 开发者都必备的技能,所以快快收藏吧! 日期 ...

  5. 45个非常有用的 Oracle 查询语句小结

    45个非常有用的 Oracle 查询语句小结 这里我们介绍的是 40+ 个非常有用的 Oracle 查询语句,主要涵盖了日期操作,获取服务器信息,获取执行状态,计算数据库大小等等方面的查询.这些是所有 ...

  6. 45 个非常有用的 Oracle 查询语句(转)

    这里我们介绍的是 40+ 个非常有用的 Oracle 查询语句,主要涵盖了日期操作,获取服务器信息,获取执行状态,计算数据库大小等等方面的查询.这些是所有 Oracle 开发者都必备的技能,所以快快收 ...

  7. Oracle查询速度慢的原因总结

    Oracle查询速度慢的原因总结 查询速度慢的原因很多,常见如下几种:1,没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷)2,I/O吞吐量小,形成了瓶颈效应.3,没有创建计算列导致 ...

  8. 40+ 个非常有用的 Oracle 查询语句

    40+ 个非常有用的 Oracle 查询语句,主要涵盖了日期操作,获取服务器信息,获取执行状态,计算数据库大小等等方面的查询.这些是所有 Oracle 开发者都必备的技能,所以快快收藏吧! 日期/时间 ...

  9. 45个很实用的 Oracle 查询语句小结

     这里我们介绍的是 40+ 个很实用的 Oracle 查询语句,主要涵盖了日期操作,获取server信息.获取运行状态.计算数据库大小等等方面的查询. 这些是全部 Oracle 开发人员都必备的技 ...

随机推荐

  1. MVC Filter自定义验证(拦截)

    namespace QS.Web.Extensions { /// <summary> /// 验证session.权限 状态 /// </summary> [Attribut ...

  2. 实现输出h264直播流的rtmp服务器 flash直播服务器

    http://www.cnblogs.com/haibindev/archive/2012/04/16/2450989.html 实现输出h264直播流的rtmp服务器 RTMP(Real Time ...

  3. ASP和PHP限制IP访问 只允许指定IP访问 允许*号通配符过滤IP

    /** * 检测访问的ip是否为规定的允许的ip * Enter description here ... */ function check_ip(){ $ALLOWED_IP=array('192 ...

  4. oracle级联删除 触发器

    CREATE TABLE STUDENT( --创建学生表  ID NUMBER(10) PRIMARY KEY,   --主键ID  SNAME VARCHAR2(20),  CLASSNAME V ...

  5. mysql error笔记1

    mysql视图问题: The user specified as a definer ('root'@'%') does not exist 原因:由于root用户对全局host无访问权限,给root ...

  6. websocket++简单使用例子

    前言 html5支持使用websocket协议与服务器保持一个长连接,方便双方互相传输数据,而且服务器也能主动发送信息给客户端,而在这之前使用HTTP是很难做到的.下面介绍使用C++实现的websoc ...

  7. java编程思想,对象导论

    程序设计的本质就是使用编程语言解决某一类具体问题.对问题的定义叫建模,例如定义问题域中的各种名词,动作,结果等.针对具体的问题提出的解决方案叫算法. 面向对象程序设计的挑战之一,就是在问题空间的元素和 ...

  8. Scala - error: not found: value SortedMap

    先 IMPORT!!!! scala> import scala.collection._import scala.collection._ scala>  SortedMap(" ...

  9. 数据库开发 MySQL

    MySQL是Web世界中使用最广泛的数据库服务器.SQLite的特点是轻量级.可嵌入,但不能承受高并发访问,适合桌面和移动应用.而MySQL是为服务器端设计的数据库,能承受高并发访问,同时占用的内存也 ...

  10. ubuntu 下安装 apache php mysql

    ubuntu 安装 apache+php+mysql1.打开终端,输入“sudo apt-get install apache2”,回车;(安装apache2.0或2.x新版本,系统会自动查找新的版本 ...