热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

Oracle内联视图优化,视图合并的抉择

Oracle内联视图优化,视图合并的抉择内联视图in-lineview,就是sql中from后面有select子查询,或者sql中包含有用createview创建的视图,CBO可能会将内联视图或者视图展开,进行相应的等价改写,这

===================================================== Oracle 内联视图优化,视图合并的抉择 内联视图in-line view,就是sql中from后面有select子查询,或者sql中包含有用create view创建的视图,CBO可能会将内联视图或者视图展开,进行相应的等价改写,这

=====================================================


Oracle 内联视图优化,视图合并的抉择

内联视图in-line view,就是sql中from后面有select子查询,或者sql中包含有用create view创建的视图,CBO可能会将内联视图或者视图展开,进行相应的等价改写,这种就叫视图合并。直接看一个sql的执行计划

1. user_tables和dba_objects都是静态数据字典,我们来看下sql的执行计划

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

SELECTto_char(wmsys.wm_concat(a.TABLE_NAME))

FROMuser_tablesa,dba_objectsb

WHEREa.TABLE_NAME=b.OBJECT_NAME

ANDb.OWNER='SCOTT'

ANDB.OBJECT_TYPE='TABLE';

执行计划

----------------------------------------------------------

Planhashvalue:555706832

-------------------------------------------------------------------------------------------------------

|Id |Operation |Name |Rows |Bytes|Cost(%CPU)|Time |

-------------------------------------------------------------------------------------------------------

| 0|SELECTSTATEMENT | | 1| 190| 1750 (1)|00:00:22|

| 1| SORTAGGREGATE | | 1| 190| | |

|* 2| HASHJOINRIGHTOUTER | | 2425| 449K| 1750 (1)|00:00:22|

| 3| TABLEACCESSFULL |SEG$ | 5832|64152| 38 (0)|00:00:01|

|* 4| HASHJOINRIGHTOUTER | | 2385| 416K| 1711 (1)|00:00:21|

| 5| INDEXFULLSCAN |I_USER2 | 93| 372| 1 (0)|00:00:01|

|* 6| HASHJOINOUTER | | 2385| 407K| 1710 (1)|00:00:21|

|* 7| HASHJOINOUTER | | 2385| 388K| 1662 (1)|00:00:20|

|* 8| HASHJOIN | | 2385| 377K| 1614 (1)|00:00:20|

| 9| TABLEACCESSFULL |TS$ | 7| 21| 3 (0)|00:00:01|

| 10| NESTEDLOOPS | | 2385| 370K| 1611 (1)|00:00:20|

|*11| HASHJOIN | | 2385| 300K| 1517 (1)|00:00:19|

| 12| VIEW |DBA_OBJECTS| 2359|58975| 1313 (1)|00:00:16|

| 13| UNION-ALL | | | | | |

|*14| TABLEACCESSBYINDEXROWID |SUM$ | 1| 9| 1 (0)|00:00:01|

|*15| INDEXUNIQUESCAN |I_SUM$_1 | 1| | 0 (0)|00:00:01|

|*16| FILTER | | | | | |

|*17| HASHJOIN | | 25| 3050| 48 (3)|00:00:01|

| 18| NESTEDLOOPS | | 25| 2500| 46 (0)|00:00:01|

| 19| TABLEACCESSBYINDEXROWID|USER$ | 1| 17| 1 (0)|00:00:01|

|*20| INDEXUNIQUESCAN |I_USER1 | 1| | 0 (0)|00:00:01|

|*21| TABLEACCESSBYINDEXROWID|OBJ$ | 25| 2075| 45 (0)|00:00:01|

|*22| INDEXRANGESCAN |I_OBJ5 | 25| | 27 (0)|00:00:01|

| 23| INDEXFULLSCAN |I_USER2 | 93| 2046| 1 (0)|00:00:01|

|*24| TABLEACCESSBYINDEXROWID |IND$ | 1| 8| 2 (0)|00:00:01|

|*25| INDEXUNIQUESCAN |I_IND1 | 1| | 1 (0)|00:00:01|

| 26| NESTEDLOOPS | | 1| 29| 2 (0)|00:00:01|

|*27| INDEXFULLSCAN |I_USER2 | 1| 20| 1 (0)|00:00:01|

|*28| INDEXRANGESCAN |I_OBJ4 | 1| 9| 1 (0)|00:00:01|

|*29| FILTER | | | | | |

| 30| NESTEDLOOPS | | 1| 96| 1 (0)|00:00:01|

| 31| TABLEACCESSBYINDEXROWID|USER$ | 1| 17| 1 (0)|00:00:01|

|*32| INDEXUNIQUESCAN |I_USER1 | 1| | 0 (0)|00:00:01|

|*33| INDEXRANGESCAN |I_LINK1 | 1| 79| 0 (0)|00:00:01|

| 34| MERGEJOINCARTESIAN | | 2530| 256K| 203 (2)|00:00:03|

|*35| HASHJOIN | | 1| 68| 1(100)|00:00:01|

|*36| FIXEDTABLEFULL |X$KSPPI | 1| 55| 0 (0)|00:00:01|

| 37| FIXEDTABLEFULL |X$KSPPCV | 100| 1300| 0 (0)|00:00:01|

| 38| BUFFERSORT | | 2530|91080| 203 (2)|00:00:03|

|*39| TABLEACCESSFULL |OBJ$ | 2530|91080| 203 (2)|00:00:03|

|*40| TABLEACCESSCLUSTER |TAB$ | 1| 30| 1 (0)|00:00:01|

|*41| INDEXUNIQUESCAN |I_OBJ# | 1| | 0 (0)|00:00:01|

| 42| INDEXFASTFULLSCAN |I_OBJ1 |73384| 358K| 47 (0)|00:00:01|

| 43| INDEXFASTFULLSCAN |I_OBJ1 |73384| 573K| 47 (0)|00:00:01|

-------------------------------------------------------------------------------------------------------

可以看到id=12这一步有一个view关键字,这一步正好是提取dba_objects视图的数据,然后此表和id=34这一步进行hash join,但hash join的表并不是sql当中的user_tables,而且在整个执行计划当中都找不到这个视图的信息,此视图被展开了。但这种情况我们是不需要展开的

2. 既然不需要展开,我们直接使用hint禁止视图合并

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

SQL>SELECT/*+ no_merge(a) */to_char(wmsys.wm_concat(a.TABLE_NAME))

2 FROMuser_tablesa,dba_objectsb

3 WHEREa.TABLE_NAME=b.OBJECT_NAME

4 ANDb.OWNER='SCOTT'

5 ANDB.OBJECT_TYPE ='TABLE';

执行计划

----------------------------------------------------------

Planhashvalue:3412902540

--------------------------------------------------------------------------------------------------

|Id |Operation |Name |Rows |Bytes|Cost(%CPU)|Time |

--------------------------------------------------------------------------------------------------

| 0|SELECTSTATEMENT | | 1| 50| 1756 (1)|00:00:22|

| 1| SORTAGGREGATE | | 1| 50| | |

|* 2| HASHJOIN | | 2359| 115K| 1756 (1)|00:00:22|

| 3| VIEW |DBA_OBJECTS| 2359|58975| 1313 (1)|00:00:16|

| 4| UNION-ALL | | | | | |

|* 5| TABLEACCESSBYINDEXROWID |SUM$ | 1| 9| 1 (0)|00:00:01|

|* 6| INDEXUNIQUESCAN |I_SUM$_1 | 1| | 0 (0)|00:00:01|

|* 7| FILTER | | | | | |

|* 8| HASHJOIN | | 25| 3050| 48 (3)|00:00:01|

| 9| NESTEDLOOPS | | 25| 2500| 46 (0)|00:00:01|

| 10| TABLEACCESSBYINDEXROWID|USER$ | 1| 17| 1 (0)|00:00:01|

|*11| INDEXUNIQUESCAN |I_USER1 | 1| | 0 (0)|00:00:01|

|*12| TABLEACCESSBYINDEXROWID|OBJ$ | 25| 2075| 45 (0)|00:00:01|

|*13| INDEXRANGESCAN |I_OBJ5 | 25| | 27 (0)|00:00:01|

| 14| INDEXFULLSCAN |I_USER2 | 93| 2046| 1 (0)|00:00:01|

|*15| TABLEACCESSBYINDEXROWID |IND$ | 1| 8| 2 (0)|00:00:01|

|*16| INDEXUNIQUESCAN |I_IND1 | 1| | 1 (0)|00:00:01|

| 17| NESTEDLOOPS | | 1| 29| 2 (0)|00:00:01|

|*18| INDEXFULLSCAN |I_USER2 | 1| 20| 1 (0)|00:00:01|

|*19| INDEXRANGESCAN |I_OBJ4 | 1| 9| 1 (0)|00:00:01|

|*20| FILTER | | | | | |

| 21| NESTEDLOOPS | | 1| 96| 1 (0)|00:00:01|

| 22| TABLEACCESSBYINDEXROWID|USER$ | 1| 17| 1 (0)|00:00:01|

|*23| INDEXUNIQUESCAN |I_USER1 | 1| | 0 (0)|00:00:01|

|*24| INDEXRANGESCAN |I_LINK1 | 1| 79| 0 (0)|00:00:01|

| 25| VIEW |USER_TABLES| 2573|64325| 442 (2)|00:00:06|

|*26| HASHJOINRIGHTOUTER | | 2573| 414K| 442 (2)|00:00:06|

| 27| TABLEACCESSFULL |SEG$ | 5832|64152| 38 (0)|00:00:01|

|*28| HASHJOINRIGHTOUTER | | 2530| 380K| 403 (2)|00:00:05|

| 29| INDEXFULLSCAN |I_USER2 | 93| 372| 1 (0)|00:00:01|

|*30| HASHJOINOUTER | | 2530| 370K| 402 (2)|00:00:05|

|*31| HASHJOINOUTER | | 2530| 350K| 354 (2)|00:00:05|

|*32| HASHJOIN | | 2530| 338K| 306 (2)|00:00:04|

| 33| TABLEACCESSFULL |TS$ | 7| 21| 3 (0)|00:00:01|

| 34| NESTEDLOOPS | | 2530| 331K| 302 (1)|00:00:04|

| 35| MERGEJOINCARTESIAN | | 2530| 256K| 203 (2)|00:00:03|

|*36| HASHJOIN | | 1| 68| 1(100)|00:00:01|

|*37| FIXEDTABLEFULL |X$KSPPI | 1| 55| 0 (0)|00:00:01|

| 38| FIXEDTABLEFULL |X$KSPPCV | 100| 1300| 0 (0)|00:00:01|

| 39| BUFFERSORT | | 2530|91080| 203 (2)|00:00:03|

|*40| TABLEACCESSFULL |OBJ$ | 2530|91080| 203 (2)|00:00:03|

|*41| TABLEACCESSCLUSTER |TAB$ | 1| 30| 1 (0)|00:00:01|

|*42| INDEXUNIQUESCAN |I_OBJ# | 1| | 0 (0)|00:00:01|

| 43| INDEXFASTFULLSCAN |I_OBJ1 |73384| 358K| 47 (0)|00:00:01|

| 44| INDEXFASTFULLSCAN |I_OBJ1 |73384| 573K| 47 (0)|00:00:01|

--------------------------------------------------------------------------------------------------

现在可以在执行计划中看到id=3和id=25这两步都是视图,通过hash join连接。

疑问:为什么这里不需要视图合并?

答曰:如果不视图合并,那整个视图就会当成一整块,在sql执行的时候,这个视图就是一个结果集,然后再去和另一个结果集关联。如果合并了的话,那这个视图就会被拆散,视图里面的关联就会分开run,并不是每次视图合并都是高效的。

在执行计划中,如果看到view关键字,说明视图没有展开,也就是视图没有合并,如果本来sql中有内联视图或者视图,但执行计划中没有看到view关键字,那这个sql就进行了视图合并。

此外还需要注意的是,如果sql中的内联视图有聚合等操作,比如rownum,start with,connect by,union,union all,rollup,cube等,这种内联视图就不能展开,因为内联视图被固化了,碰到这种情况就需要注意,如果内联视图中结果集很大,那sql估计就要改写了,因为这个内联视图会最先执行。

  • http://www.savedba.com/?p=816

============================================
3.1.1.1 内联视图合并

2013-02-25 16:45 黄玮 机械工业出版社 我要评论(0) 字号:T | T

综合评级:

想读(1) 在读(0) 已读(0) 品书斋鉴(0) 已有1人发表书评

《Oracle高性能SQL引擎剖析:SQL优化与调优机制详解》第3章查询转换,在本章中,我们将会了解到以下内容:Oracle的逻辑优化技术中,存在哪些启发式查询转换技术,以及它们的具体含义和示例;Oracle的逻辑优化技术中,存在哪些基于代价的查询转换技术,以及它们的具体含义和示例。本节为大家介绍内联视图合并。

AD:2014WOT全球软件技术峰会北京站 课程视频发布

3.1.1.1 内联视图合并

我们以下面两个执行计划为例,简要说明视图合并技术对执行计划优化的影响,见代码清单3-1。

代码清单3-1 内联视图合并

  1. HELLODBA.COM>exec sql_explain('select /*+no_merge(o)*/* from t_tables t, v_objects_sys o where
  2. t.owner=o.owner and t.table_name = object_name and t.tablespace_name = :A and t.table_name
  3. like :B and o.status=:C', 'TYPICAL');
  4. Plan hash value: 3284354748
  5. ----------------------------------------------------------------------------------------------------
  6. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
  7. ----------------------------------------------------------------------------------------------------
  8. | 0 | SELECT STATEMENT | | 3 | 840 | 87 (3)| 00:00:01 |
  9. |* 1 | HASH JOIN | | 3 | 840 | 87 (3)| 00:00:01 |
  10. | 2 | TABLE ACCESS BY INDEX ROWID | T_TABLES | 9 | 1836 | 13 (8)| 00:00:01 |
  11. | 3 | BITMAP CONVERSION TO ROWIDS | | | | | |
  12. | 4 | BITMAP AND | | | | | |
  13. | 5 | BITMAP CONVERSION FROM ROWIDS| | | | | |
  14. |* 6 | INDEX RANGE SCAN | T_TABLES_IDX3 | 184 | | 1 (0)| 00:00:01 |
  15. | 7 | BITMAP CONVERSION FROM ROWIDS| | | | | |
  16. | 8 | SORT ORDER BY | | | | | |
  17. |* 9 | INDEX RANGE SCAN | T_TABLES_PK | 184 | | 2 (0)| 00:00:01 |
  18. | 10 | VIEW | V_OBJECTS_SYS | 571 | 43396 | 73 (0)| 00:00:01 |
  19. | 11 | TABLE ACCESS BY INDEX ROWID | T_OBJECTS | 571 | 47393 | 73 (0)| 00:00:01 |
  20. |* 12 | INDEX RANGE SCAN | T_OBJECTS_IDX1 | 103 | | 3 (0)| 00:00:01 |
  21. ----------------------------------------------------------------------------------------------------
  22. Predicate Information (identified by operation id):
  23. ---------------------------------------------------
  24. 1 - access("T"."OWNER&quo
推荐阅读
  • 基于PgpoolII的PostgreSQL集群安装与配置教程
    本文介绍了基于PgpoolII的PostgreSQL集群的安装与配置教程。Pgpool-II是一个位于PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件,提供了连接池、复制、负载均衡、缓存、看门狗、限制链接等功能,可以用于搭建高可用的PostgreSQL集群。文章详细介绍了通过yum安装Pgpool-II的步骤,并提供了相关的官方参考地址。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • Oracle Database 10g许可授予信息及高级功能详解
    本文介绍了Oracle Database 10g许可授予信息及其中的高级功能,包括数据库优化数据包、SQL访问指导、SQL优化指导、SQL优化集和重组对象。同时提供了详细说明,指导用户在Oracle Database 10g中如何使用这些功能。 ... [详细]
  • 本文介绍了adg架构设置在企业数据治理中的应用。随着信息技术的发展,企业IT系统的快速发展使得数据成为企业业务增长的新动力,但同时也带来了数据冗余、数据难发现、效率低下、资源消耗等问题。本文讨论了企业面临的几类尖锐问题,并提出了解决方案,包括确保库表结构与系统测试版本一致、避免数据冗余、快速定位问题等。此外,本文还探讨了adg架构在大版本升级、上云服务和微服务治理方面的应用。通过本文的介绍,读者可以了解到adg架构设置的重要性及其在企业数据治理中的应用。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了使用postman进行接口测试的方法,以测试用户管理模块为例。首先需要下载并安装postman,然后创建基本的请求并填写用户名密码进行登录测试。接下来可以进行用户查询和新增的测试。在新增时,可以进行异常测试,包括用户名超长和输入特殊字符的情况。通过测试发现后台没有对参数长度和特殊字符进行检查和过滤。 ... [详细]
  • 本文详细介绍了MysqlDump和mysqldump进行全库备份的相关知识,包括备份命令的使用方法、my.cnf配置文件的设置、binlog日志的位置指定、增量恢复的方式以及适用于innodb引擎和myisam引擎的备份方法。对于需要进行数据库备份的用户来说,本文提供了一些有价值的参考内容。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 本文由编程笔记小编整理,介绍了PHP中的MySQL函数库及其常用函数,包括mysql_connect、mysql_error、mysql_select_db、mysql_query、mysql_affected_row、mysql_close等。希望对读者有一定的参考价值。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • MyBatis错题分析解析及注意事项
    本文对MyBatis的错题进行了分析和解析,同时介绍了使用MyBatis时需要注意的一些事项,如resultMap的使用、SqlSession和SqlSessionFactory的获取方式、动态SQL中的else元素和when元素的使用、resource属性和url属性的配置方式、typeAliases的使用方法等。同时还指出了在属性名与查询字段名不一致时需要使用resultMap进行结果映射,而不能使用resultType。 ... [详细]
  • 本文详细介绍了在ASP.NET中获取插入记录的ID的几种方法,包括使用SCOPE_IDENTITY()和IDENT_CURRENT()函数,以及通过ExecuteReader方法执行SQL语句获取ID的步骤。同时,还提供了使用这些方法的示例代码和注意事项。对于需要获取表中最后一个插入操作所产生的ID或马上使用刚插入的新记录ID的开发者来说,本文提供了一些有用的技巧和建议。 ... [详细]
author-avatar
谁是我我2010
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有