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. 20151216JqueryUI---dialog代码备份

    $(function () { $('#search_button').button(); /*$('#reg').dialog({ focus:function(e,ui){ alert('注册') ...

  2. android开发者博客二月-Marshmallow and User Data

    又是一篇翻译,这篇快了很多,不过也花了快一个小时,可能熟悉一点.关于6.0权限的,让你做用户认为正确的事情. Marshmallow and UserData 2016,2,1 棉花糖和用户数据 由J ...

  3. MVC小系列(六)【无刷新的验证码】

    做个无刷新的验证码功能: 第一步:首先,在公用项目中建立一个生成图片验证码的类型ValidateCode /// <summary> /// 生成验证码对象 /// </summar ...

  4. Asp.Net alert弹出提示信息的5种方法

    1.ClientScript.RegisterStartupScript(GetType(),"message","<script>alert('第一种方式, ...

  5. C10K问题2

    http://blog.csdn.net/zhoudaxia/article/details/12920993 是时候让 Web 服务器同时处理一万客户端了,你不觉得吗?毕竟,现在的 Web 是一个大 ...

  6. 计算Android屏幕解锁组合数

    晚饭时和同事聊到安卓屏幕解锁时会有多少种解锁方案,觉得很有趣,吃完饭开始想办法解题,花了大概2个小时解决.思路如下: 使用索引值0-9表示从左到右.从上到下的9个点,行.列号很容易从索引值得到: 使用 ...

  7. jsp与Action值得对应

    例如:Action中有一个全局对象dictionary,对象有种A,B,C三个属性. 1.通过后台将Action中的值传到jsp,需要el表达式. 页面取到A的值 <input name=&qu ...

  8. iOS NSNumber语法糖

    BOOL equal; NSNumber * num1 = [NSNumber numberWithInteger:]; NSNumber * num2 = @; equal = [num1 isEq ...

  9. c#接口深入一步探究其作用,适合新人了解

    前言 前一篇浅显的述说了一下c#接口的作用,并用了一个不怎么好的例子述说了一下.时隔一天,在看完大家的评论后我在论坛中查看了很多前辈们对c#接口的描述,发现大家对例子的说明不是太容易让我们这些新人理解 ...

  10. redis基本数据类型【3】-List类型

    列表类型采用双向链表实现的,借助列表类型redis还可以作为队列使用,一个列表类型key最多能容纳2^32-1个元素 1.向列表两端增加元素 #向左边增加元素,返回增加后列表的长度 lpush key ...