设为首页 收藏本站
查看: 418|回复: 0

[经验分享] Oracle表联结之嵌套循环

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2015-8-17 09:27:45 | 显示全部楼层 |阅读模式
1.单表访问: 分表,分区,建索引,全表扫描---开并行, 永远把它 放内存,压缩


2.多表关联,任何时刻只能是2个表关联,得到的结果集再和其他表关联。
3.嵌套循环:Oracle从较小结果集(驱动表/外部表)中读取一行,然后和较大结果集(被探查表/内部表)中的所有数据逐条进行比较(嵌套循环可以用于非等值连接),如果符合规则,就放入结果集中,然后取较小结果集的下一条数据继续进行循环,直到结束。嵌套循环只适合输出少量结果集或者是用于快速输出结果集。其实相当于双层FOR循环。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
SQL> select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID bv300dy9b7gyn, child number 0
-------------------------------------
select /*+ first_rows */ e.ename,e.job,d.dname from emp e,dept d  where
e.deptno=d.deptno and e.sal<2000
Plan hash value: 3625962092
-----------------------------------------------------------------------------------------------------------
| Id  | Operation       | Name    | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |
-----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |        |      1 |  | 7 |00:00:00.14 |      18 | 8 |
|   1 |  NESTED LOOPS       |        |      1 |      4 | 7 |00:00:00.14 |      18 | 8 |
|   2 |   NESTED LOOPS       |        |      1 |      4 | 7 |00:00:00.14 |      11 | 7 |
|*  3 |    TABLE ACCESS FULL      | EMP     |      1 |      4 | 7 |00:00:00.12 |       7 | 6 |
|*  4 |    INDEX UNIQUE SCAN      | PK_DEPT |      7 |      1 | 7 |00:00:00.01 |       4 | 1 |
|   5 |   TABLE ACCESS BY INDEX ROWID| DEPT    |      7 |      1 | 7 |00:00:00.01 |       7 | 1 |
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   3 - filter("E"."SAL"<2000)
   4 - access("E"."DEPTNO"="D"."DEPTNO")

24 rows selected.



离关键字近的是驱动表,嵌套循环的rows是错误的,嵌套循环的算法,比如a NL b,如a表有1000条,从a表中取1000条数据,扫描一次a,把这1000条数据传给b,然后b表被扫描1000次,那么取出的a表的数据放在什么地方?匹配完一条然后立马返回,NL不需要PGA,因为不用缓存数据,如果多层NL,仍然是存PGA,多层NL容易引起CBC,
嵌套循环中,过滤后返回结果集的小的当驱动表,在外连接中,嵌套循环不能修改驱动表,在嵌套循环中,被驱动表的连接列一定要有索引,从上面执行计划可以看到E的deptno传值给D表的deptno,驱动表的连接列不用建索引,
nl 必须是驱动表返回数据量很少的时候才走,在sql语句中有count,group by,distinct,sum等关键字,不能走NL,如果OLTP系统,有大量的distinct,只能说明表设计有问题,用中间表把所有的关联去重解决distinct,
如果在执行计划里面有很多NL,从最里面开始搞,如果最里面错误了,那么外面的NL全部错误,由里向外不断看NL.
怎样判断NL是否是对的?1,看驱动表返回的数据量,2,看被驱动表是否走索引,3.看最终返回多少结果集。那么第3条最重要。最终返回多少结果集决定是否走NL还是HASH.

如果A NL B,返回10w条数据,如果a:b=1:1,那么a至少返回10w条数据,然后b表被扫描10w次,如果a:b=1:10,那么a至少返回1w数据,那么b表被扫描1w次,b表走索引,b表走一次索引,回表10条数据,那么b表总回表次数是10w次,所以在NL中,被驱动表不管被扫描多少次,那么回表次数是最终返回数据条数,所以嵌套循环不适合大量数据,根本原因在于回表或者回表再过滤,如果不用回表或回表再过滤,那么NL非常有效。


被驱动表的连接列要基数很高,如果基数很低,不能走NL,如1:1w,1:N,然后N太大

NL只需要SGA,不需要PGA,NL支持非等值jion,而HASH join只支持等值关联。

判断是否走NL和HASH,根据最终返回的结果集来判断,其次驱动表返回的行数,再是被驱动表的jion列的基数。

错误NL,1.单次返回大量数据,如100w


附:查询访问表所有字段的sql信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
WITH t AS
(SELECT a.object_name "表名",
         a.sql_id,
         c.sql_text,
         c.executions,
         (regexp_count(prjection, ',', 1) + 1) / 2 "访问列数",
         COUNT(b.column_name) "总列数",
         d.bytes / 1024 / 1024 "表体积_MB"
    FROM v$sql_plan a, dba_tab_columns b, v$sql c, dba_segments d
   WHERE a.object_owner = b.owner
     AND a.object_name = b.table_name
     AND a.object_owner = 'EOL'
     AND a.sql_id = c.sql_id
     AND a.object_name = d.segment_name
     AND a.object_owner = d.owner
   GROUP BY (regexp_count(prjection, ',', 1) + 1) / 2,a.object_name,
            a.sql_id,
            c.sql_text,
            c.executions,
            d.bytes / 1024 / 1024)
SELECT * FROM t WHERE t.访问列数 = t.总列数 ORDER BY 表体积_MB,executions DESC;



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-100063-1-1.html 上篇帖子: Oracle 学习之RAC(七) 集群启动解析 下篇帖子: oracle RAC 使用Jumbo Frames Oracle
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表