Oracle数据库性能优化-表连接与优化器(基于ORACLE数据库sql优化)

1 嵌套循环连接 

条件1: 如果驱动表所对应的驱动结果集的记录数较少 ,同时在被驱动的表的连接列又存在唯一性索引 (或者在被驱动表的连接列有选择性非常好的非唯一索引)

那么使用嵌套循环连接。如果驱动表对应的驱动结果集对应的记录数较大,则即使连接列存在索引,效率也不会高。

条件2:驱动结果集为大表,通过谓词条件筛选后,能够将驱动结果集降低。

优点:嵌套循环连接相比其他连接,可以实现快速响应,即它第一时间返回已经满足条件的记录行数。

总结:较小的驱动结果集,被驱动表连接列存在选择性比较好的索引

案例 1 

select *from a ,b where a.date=sysdate-10 and a.id=b.id(其中a表通过谓词帅选后有10W,b表数据量为3000, 则执行计划为 A表驱动 ,b表被驱动,走 nl连接,连接列有唯一索引 巴士)

2  哈希连接

1 驱动结果集数量较大,连接列不存在合适的索引,且驱动结果集通过hash 运气算对应的HASH table 可以完全容在PGA中。

2 连接列可选择性很好,如果不好,可能导致hash table中记录数较多,导致高的cpu消耗,很低的逻辑读取。(读取PGA hash table)。

3 反连接

对于使用not in not exists <>ALL条件产生的子查询展开使用的连接。

SQL> create  table ac1 as select * from dba_objects;

表已创建。

SQL> create table ac2 as select * from ac1
  2  ;

表已创建。

SQL> select * from ac1 where ac1.object_id not in (select object_id from ac2);

未选定行

SQL> set autotrace traceonly;
SQL> select * from ac1 where ac1.object_id not in (select object_id from ac2);

未选定行

执行计划
----------------------------------------------------------
Plan hash value: 2231603900

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

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

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

|   0 | SELECT STATEMENT        |      | 72330 |    34M|       |  2547   (1)| 00

:00:01 |

|*  1 |  HASH JOIN RIGHT ANTI NA|      | 72330 |    34M|  1712K|  2547   (1)| 00

:00:01 |

|   2 |   TABLE ACCESS FULL     | AC2  | 69805 |   886K|       |   387   (1)| 00

:00:01 |

|   3 |   TABLE ACCESS FULL     | AC1  | 72330 |    33M|       |   389   (1)| 00

:00:01 |


Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("AC1"."OBJECT_ID"="OBJECT_ID")
   - dynamic statistics used: dynamic sampling (level=2)

统计信息
----------------------------------------------------------
          0  recursive calls
          5  db block gets
       1435  consistent gets
          0  physical reads
          0  redo size
       2168  bytes sent via SQL*Net to client
        597  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed

SQL>
 

半连接s

HASH JOIN SEMI

select * from t1 where t1.id in(select t2.id from t2);

select *from t1 where exists(select 1 from t2 where t1.id=t2.id);

分析案例:

1个sql 对应3个执行计划。即3个plan_HASH_VALUE.

在问题出现期间选择value1的执行计划。(一个740W数据的表进行全表扫描),对应的几个sql对应的cost值基本接近。

案例分析:

1 查看统计信息 。

2 查看真是表数据信息

原因分析总结:1 根据执行计划统计信息发现对一个740w表进行全表扫描cost值仅为10,(应该在几百k才对),且统计信息num rows显示为600多w比较准确。

                         2 通过分析发现 由于修改了会话级别的optimizer MODE参数为first_rows_10导致 对全表扫描预估的cost值不准确,导致CBO在选择执行计话时,选择了错误的cost值得执行计划。

                         3导致CBO评估出①个实际数据量730W且统计信息准确的大表全表扫描操作成本仅为2的原因,是参数optimizer_mode被修改为first_rows_10,导致了系统登录间隙性变慢的问题。

SQL> show parameter mode

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
instance_mode                        string      READ-WRITE
optimizer_mode                       string      ALL_ROWS
remote_dependencies_mode             string      TIMESTAMP
result_cache_mode                    string      MANUAL
SQL>

知识点总结:

1 通过b树索引的查询效率,不会因为表数据量的增加而降低。

2 关键字(+)在哪里出现,则表明对应的对象要以null来补全。

3 Oracle索引跳跃式扫描,前导列distinct值越少越好。

4 大表也可以作为驱动表,但是需要谓词条件的access或者filter,使数据量降下来。

猜你喜欢

转载自blog.csdn.net/oradbm/article/details/113554365