《oracle数据分析和动态采样》引言:oracle数据库性能调优最需要重视的也最常遇到的就是sql执行效率,而反映sql效率最直观的工具就是cbo生成的执行计划,那么如
《oracle 数据分析和动态采样》
引言:oracle 数据库性能调优最需要重视的也最常遇到的就是sql执行效率,而反映sql效率最直观的工具就是cbo生成的执行计划,那么如何让cbo生成最精准的效率最高的执行计划成为我们当前需要研究的课题。同一条语句,好的执行计划能带来飞一样的速度,坏的执行计划让我们痛苦不堪,下面我们从原理到实践来把如何产生高效计划的方法教给大家。
一 cbo介绍
cbo全称叫cost based optimization基于代价优化器,它是一个数学模型,同一个sql语句在不同的oracle版本中计算出来的代价结果也是不一样的,因为每个版本cbo优化器的设计结构有很大不同,现在还不是很完善很智能很通人性,因此我们不能完全依赖它,只能辅助我们。
如何生成精确的执行计划:公式数据+cbo=执行计划,传入cbo的数据越精确得到结果越精确,我们能做的保证输入数据更准确,通过精确数据计算出精确执行计划
二演示一个表分析后执行计划比动态采样更准确的例子
动态采样:顾名思义就是oracle自动为你进行的初步数据分析,由于是随机在表上取一些数据,因此并不能保证得出的执行计划很准确,只能作为一种辅助分析手段,在不得已的情况下来分析数据,有一定的局限性。
场景:当表没有分析信息时,香港服务器,oracle会使用动态采样技术,而且动态采样是在sql硬解析的时候发生的,传入->cbo参数->生成执行计划。
级别:oracle 10g oracle 11g 默认动态采样级别是2,它有level1-10,设置的级别越高采集的数据块越多,结果越精确,运行时间越长,level10对所有数据进行采样分析。
实验
leo1@leo1> drop table leo1 purge;清理环境
table dropped.
leo1@leo1> drop table leo2 purge;
table dropped.
leo1@leo1> create table leo1 as select * from dba_objects;创建leo1表
table created.
leo1@leo1> create table leo2 as select * from leo1;创建leo2表,采用leo1一样数据和结构
table created.
leo1@leo1> col segment_name for a10
leo1@leo1> select segment_name,extents,blocks from dba_segments where segment_name in ('leo1','leo2');
segment_na extents blocks
---------- ---------- -------------- -------------- ----
leo1 24 1152
leo2 24 1152
查询leo1和leo2表这两个段对象存储参数,都是占用24个区,1152个块,2个表一模一样嘛
leo1@leo1> col table_name for a10
leo1@leo1> select table_name,num_rows,blocks,status from dba_tables wheretable_name in ('leo1','leo2');
table_name num_rows blocks status
---------- ---------- ---------- ------------ ---------- ------------
leo1 valid
leo2 valid
在这个数据字典里只显示表名和当前状态(有效),没有行信息和块信息,这是为神马呢,嗯从上面的操作可以看出,我们只是建立了表,但没有分析表统计信息,现在我们分析一下后看看效果
leo1@leo1> execute dbms_stats.gather_table_stats('leo1','leo1');对leo1表进行统计分析
pl/sql procedure successfully completed.
leo1@leo1> select table_name,num_rows,blocks,status from dba_tables wheretable_name in ('leo1','leo2');
table_name num_rows blocks status
---------- ---------- ---------- ------------ ---------- ------------
leo1 71968 1051 valid
leo2 valid
现在leo1表已经有行信息和块信息了,leo2由于没有进行表分析现在还什么都没有
leo1@leo1> set autotrace trace exp
leo1@leo1> select * from leo1 where object_id=10000;
execution plan
----------------------------------------------------------
plan hash value: 2716644435
--------------------------------------------------------------------------
| id | operation | name | rows | bytes | cost (%cpu)| time |
--------------------------------------------------------------------------
| 0 | select statement | | 1 | 97 | 287 (1)| 00:00:04 |
|* 1 | table access full| leo1 | 1 | 97 | 287 (1)| 00:00:04 |
--------------------------------------------------------------------------
predicate information (identified by operation id):
---------------------------------------------------
1 - filter(object_id=10000)