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. store procedure example

    SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- ...

  2. 使用instsrv.exe+srvany.exe将应用程序安装为windows服务[转]

      转自:http://qingmu.blog.51cto.com/4571483/1248649 一.什么是instsrv.exe和srvany.exe instsrv.exe.exe和srvany ...

  3. == 和 equals()的区别

    package com.liaojianya.chapter1; /** * This program demonstrates the difference between == and equal ...

  4. 加载jar文件输出class和method

    package file import java.util.jar.JarEntry import java.util.jar.JarFile import org.junit.Test; class ...

  5. websocket++简单使用例子

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

  6. 暑假集训(1)第一弹 -----士兵队列训练问题(Hdu1276)

    Description 某部队进行新兵队列训练,将新兵从一开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始一至二报数,凡报到二的出列,剩下的向小序号方向靠拢,再从头开始进行一至三报数,凡报 ...

  7. (转)Libevent(3)— 基础库

    转自:http://name5566.com/4202.html 参考文献列表:http://www.wangafu.net/~nickm/libevent-book/ 此文编写的时候,使用到的 Li ...

  8. 第3章文件I/O总结

    1. open和create函数在fcntl.h中,close.lseek.read.write函数在unistd.h中 open函数通过进程有效用户ID判断读文件的权限 可以调用access函数判断 ...

  9. ubuntu tengine 安装

    参考文章:http://wangyan.org/blog/install-openssl-from-source.html http://www1.site90.com/Linux/405.html ...

  10. 面试题:实现LRUCache::Least Recently Used的缩写,意思是最近最少使用,它是一种Cache替换算法

    Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...