--exec dbms_stats.gather_table_STATS('SA',upper('temp_T_ORG_Admin'),cascade => true); --执行后数据量4
--1)
select org.fid,REA.FPERSONID
from temp_T_ORG_Admin org,T_HR_EMPORGRELATION rea
where ORG.FID=REA.FADMINORGID;
--刚开始数据量temp_T_ORG_Admin 88 ,执行计划,temp_T_ORG_Admin 88、 T_HR_EMPORGRELATION index fast full scan扫描;
--删除后数据量temp_T_ORG_Admin 4 ,执行计划 ,temp_T_ORG_Admin 88,T_HR_EMPORGRELATION index range scan扫描;
--说明:表真实数据量变化了,统计信息没有立即改变
--!!!***@@@注意:对全局临时表(即session 临时表),执行做数据量统计,是很危险的; 例如sys登录做dbms_stats.gather_table_STATS('SA',upper('temp_T_ORG_Admin'),cascade => true); 得到统计信息,这个统计信息会作用/影响所有session访问sa.temp_T_ORG_Admin的执行计划。
--可以使用hint显式让临时表使用动态采样
select /*+ dynamic_sampling(temp_T_ORG_Admin 5)*/ * from temp_T_ORG_Admin;
select /*+ dynamic_sampling(TEMP_T_ORG_ADMIN 5)*/ count(*)
from temp_T_ORG_Admin org,T_HR_EMPORGRELATION rea
where ORG.FID=REA.FADMINORGID;
-- 或者删除统计信息 (如果发现执行计划走错,删除表的统计信息,让其动态采样). 临时表可以,删除统计信息,让后锁住统计信息。
--(如果临时表数据很大,还是可以建立索引,以及收集统计信息的)
exec dbms_stats.delete_table_stats(ownname => 'SA',tabname => upper('temp_T_ORG_Admin'),cascade_indexes => true) ;
exec dbms_stats.lock_table_stats(ownname => 'SA',tabname => upper('temp_T_ORG_Admin'),stattype => 'ALL');
--2)
select org.fid,REA.FPERSONID
from middle_T_ORG_Admin org,T_HR_EMPORGRELATION rea
where ORG.FID=REA.FADMINORGID;
--middle_T_ORG_Admin普通表
--刚开始数据量middle_T_ORG_Admin 88 ,执行计划,temp_T_ORG_Admin 88、 T_HR_EMPORGRELATION index fast full scan扫描;
--删除后数据量middle_T_ORG_Admin 4 ,执行计划 ,temp_T_ORG_Admin 88,T_HR_EMPORGRELATION index range scan扫描;
--说明:经过上述操作,没有执行dbms_stats.gather_table_STATS('SA',upper('temp_T_ORG_Admin'),cascade => true);,***统计信息始终没有***!
--!!!说明:经过1、2说明表的数据量真实变了,但是不会立即改变统计信息user_TAB_STATISTICS; Oracle对没有分析的段做动态采样。
-- 导致执行计划选择T_HR_EMPORGRELATION的访问方式不同,是因为对关联表动态采样导致的。
/*
在Oracle 10g中默认对***(从来)没有分析(过)的段***做动态采样
动态采样(Dynamic Sampling)技术的最初提出是在Oracle 9i R2,在段(表,索引,分区)没有分析的情况下,
为了使CBO 优化器得到足够的信息以保证做出正确的执行计划而发明的一种技术,可以把它看做分析手段的一种补充。
当段对象没有统计信息时(即没有做分析),动态采样技术可以通过直接从需要分析的对象上收集数据块(采样)
来获得CBO需要的统计信息。
SQL> select * from sa.temp_T_ORG_Admin;
未选定行
执行计划
----------------------------------------------------------
Plan hash value: 2283835278
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 5558 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| TEMP_T_ORG_ADMIN | 1 | 5558 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement (level=2)
SQL> select * from sa.middle_T_ORG_Admin;
执行计划
----------------------------------------------------------
Plan hash value: 2591856227
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 22232 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| MIDDLE_T_ORG_ADMIN | 4 | 22232 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement (level=2) --默认动态采样的级别为2
*/
--3)
--在另外的session,sqlplus sys执行dbms_stats.gather_table_STATS('SA',upper('temp_T_ORG_Admin'),cascade => true);后,执行计划,数据量temp_T_ORG_Admin 1,T_HR_EMPORGRELATION index range scan
--在本session执行dbms_stats.gather_table_STATS('SA',upper('temp_T_ORG_Admin'),cascade => true);后,执行计划,数据量temp_T_ORG_Admin 4,T_HR_EMPORGRELATION index range scan
--!!!###提醒注意:如果执行数据量改变的操作后,执行了统计分析存储过程,这时就会使用统计信息来生成执行计划; 如果再次,执行数据量变化的操作 却 没有再执行统计信息分析,这个时候的执行计划使用的是上次的统计信息,会导致不准确。
/*
作用:
(1) CBO 依赖的是充分的统计分析信息,但是并不是每个用户都会非常认真,及时地去对每个表做分析。
为了保证执行计划都尽可能地正确,Oracle 需要使用动态采样技术来帮助CBO 获取尽可能多的信息。
(2) 全局临时表。 通常来讲,临时表的数据是不做分析的,因为它存放的数据是临时性的,可能很快就释放了,
但是当一个查询关联到这样的临时表时,CBO要想获得临时表上的统计信息分析数据,就只能依赖于动态采样了。
缺点:
(1) 采样的数据块有限,对于海量数据的表,结果难免有偏差。
(2) 采样会消耗系统资源,特别是OLTP数据库,尤其不推荐使用动态采样。
动态采样也需要额外的消耗数据库资源,所以,如果 SQL 被反复执行,变量被绑定,硬分析很少,在这样一个环境中,
是不宜使用动态采样的,就像OLTP系统。 ***动态采样发生在硬分析时,如果很少有硬分析发生,动态采样的意义就不大***。
*/
--在11G,ORACLE新推出了包DBMS_SQLDIAG,使用该包中的DUMP_TRACE过程,可以获取正在运行的SQL的执行计划的生成过程