Chinaunix首页 | 论坛 | 博客
  • 博客访问: 380583
  • 博文数量: 113
  • 博客积分: 3035
  • 博客等级: 中校
  • 技术积分: 1430
  • 用 户 组: 普通用户
  • 注册时间: 2006-11-01 16:32
文章分类
文章存档

2011年(42)

2010年(70)

2009年(1)

我的朋友

分类: Oracle

2010-10-14 10:04:37

转自http://hi.baidu.com/nsj820/blog/item/cb7a5d0ed1183cc07acbe12b.html
http://blog.csdn.net/outget1/archive/2009/11/19/4834411.aspx
一、优化器的优化方式
Oracle的优化器共有两种的优化方式,即基于规则的优化方式(Rule-Based Optimization,简称为RBO)和基于代价的优化方式(Cost-Based Optimization,简称为CBO)
1CBO方式:依词义可知,它是看语句的代价(Cost),这里的代价主要指Cpu和内存。优化器在判断是否用这种方式时,主要参照的是表及索引的统计信息。统计信息给出表的大小、有少行、每行的长度等信息。这些统计信息起初在库内是没有的,是你在做analyze后才出现的,很多的时侯过期统计信息会令优化器做出一个错误的执行计划,因些我们应及时更新这些信息。在Oracle8及以后的版本,Oracle列推荐用CBO的方式。
2RBO方式:优化器在分析SQL语句时,所遵循的是Oracle内部预定的一些规则。比如我们常见的,当一个where子句中的一列有索引时去走索引。
我们要明了,不一定走索引就是优的 ,比如一个表只有两行数据,一次IO就可以完成全表的检索,而此时走索引时则需要两次IO,这时对这个表做全表扫描(full table scan)是最好的。
二、优化器的优化模式
(Optermizer Mode)
优化模式包括Rule,Choose,First rows,All rows这四种方式:

Rule
:不用多说,即走基于规则的方式。
Choolse:默认的情况下Oracle用的便是这种方式。指的是当一个表或或索引有统计信息,则走CBO的方式,如果表或索引没统计信息,表又不是特别的小,而且相应的列有索引时,那么就走索引,RBO的方式。
First Rows
:它与Choose方式是类似的,所不同的是当一个表有统计信息时,它将是以最快的方式返回查询的最先的几行,从总体上减少了响应时间。
All Rows
:也就是我们所说的Cost的方式,当一个表有统计信息时,它将以最快的方式返回表的所有的行,从总体上提高查询的吞吐量。没有统计信息则走基于规则的方式。
三、如何设定选用哪种优化模式
1Sessions级别

通过SQL> ALTER SESSION SET OPTIMIZER_MODE=?;来设定。

2Instance级别

我们可以通过在init.ora文件中设定OPTIMIZER_MODE=RULEOPTIMIZER_MODE=CHOOSEOPTIMIZER_MODE=FIRST_ROWSOPTIMIZER_MODE=ALL_ROWS去选用以上所提的四种方式,如果你没设定OPTIMIZER_MODE参数则默认用的是Choose这种方式。

3、语句级别

这些需要用到Hint,比如
:
SELECT /*+ RULE */ a.userid,b.name,b.depart_name FROM tf_f_yhda a,tf_f_depart b WHERE a.userid=b.userid;
四、与
CBO相关统计信息的获取(analyze dbms_stats 使用)
壹、analyze 使用
1、功能
a)
搜集和删除索引、表和簇的统计信息
b)
验证表、索引和簇的结构
c)
鉴定表和簇和行迁移和行联接
d)
针对analyze的搜集和删除统计信息功能而言,oracle推荐使用DBMS_STATS包来搜集优化信息,DBMS_STATS可以并行的搜集信息,可以搜集分区表的全局信息,进一步来说,按成本的优化器只会使用DBMS_STATS包所统计出来的信息。
2、可供分析的对象
INDEX
对索引进行分析,分析的结果会放在USER_INDEXES, ALL_INDEXES, DBA_INDEXES
分析的内容:
Depth of the index from its root block to its leaf blocks (BLEVEL)
Number of leaf blocks (LEAF_BLOCKS)
Number of distinct index values (DISTINCT_KEYS)
Average number of leaf blocks for each index value (AVG_LEAF_BLOCKS_PER_KEY)
Average number of data blocks for each index value (for an index on a table) (AVG_DATA_BLOCKS_PER_KEY)
Clustering factor (how well ordered the rows are about the indexed values) (CLUSTERING_FACTOR)
TABLE
对表进行分析,分析的结果会放在USER_TABLES, ALL_TABLES, and DBA_TABLES表中,在分析表的时候,oracle也会分析基于函数的index所引用的表达式
分析的内容:
Number of rows (NUM_ROWS)
Number of data blocks below the high water mark (that is, the number of data blocks that have been formatted to receive data, regardless whether they currently contain data or are empty) (BLOCKS)
Number of data blocks allocated to the table that have never been used (EMPTY_BLOCKS) Average available free space in each data block in bytes (AVG_SPACE)
Number of chained rows (CHAIN_COUNT) Average row length, including the row's overhead, in bytes (AVG_ROW_LEN)
PARTITION | SUBPARTITION
:对分区表或索引进行分析
CLUSTER:
对簇进行分析,分析的结果会放在ALL_CLUSTERS, USER_CLUSTERS and DBA_CLUSTERS.
compute_statistics_clause
语法:COMPUTE [ SYSTEM ] STATISTICS [for_clause]
对分析对像进行精确的统计,然后把信息存储的数据字典中。可以选择对表或对字段进行分析。

computed
estimated这两种方式的统计数据都被优化器用来影响sql的执行计划
如果指定system选项就只统计系统产生的信息

for_clause FOR TABLE
:只统计表 FOR COLUMNS:只统计某个字段 FOR ALL COLUMNS:统计所有字段 FOR ALL INDEXED COLUMNS:统计索引的所有字段
estimate_statistics_clause
ESTIMATE [ SYSTEM ] STATISTICS [for_clause][SAMPLE integer { ROWS | PERCENT }]
只是对部分行做一个大概的统计。适用于大表
SAMPLE
:指定具体统计多少行,如果忽略这个参数的话,oracle会默认为1064
ROWS causes
:行数 Oracle to sample integer rows of the table or cluster or integer entries from the index. The integer must be at least 1.
PERCENT causes
:百分数

validation_clauses
分析REF或是对像的结构
EG
ANALYZE TABLE employees VALIDATE STRUCTURE CASCADE;
ANALYZE TABLE customers VALIDATE REF UPDATE;
3、分析表的限制
a)
不可以分析数据字典表
b)
不可以分析扩展表,但可以用DBMS_STATS来实现这个目的
c)
不可以分析临时表
d)
不可以计算或估计下列字段类型REFs, varrays, nested tables, LOBs (LOBs are not analyzed, they are skipped), LONGs, or object types.
贰、
dbms_stats 使用
Dbms_stats
oracle8i新增的程序包,它使统计数据的生成和处理更加方便。
--
参数
estimate_percent        --
估算抽样百分比
method_opt for table    --
只统计表 

for all indexed columns --
只统计有索引的表列
for all indexes         --
只分析统计相关索引

--
创建统计信息历史保留表
sql> exec dbms_stats.create_stat_table(ownname => 'scott',stattab => 'stat_table') ;
pl/sql procedure successfully completed
--
导出整个scheme的统计信息
sql> exec dbms_stats.export_schema_stats(ownname => 'scott',stattab => 'stat_table') ;
pl/sql procedure successfully completed
--
分析scheme
Exec dbms_stats.gather_schema_stats(
ownname => 'scott',
options => 'GATHER AUTO',
estimate_percent => dbms_stats.auto_sample_size,
method_opt => 'for all indexed columns ',
degree => 6 )
--
分析表

sql> exec dbms_stats.gather_table_stats(ownname => 'scott',tabname => 'work_list',estimate_percent => 10,method_opt=> 'for all indexed columns') ;
pl/sql procedure successfully completed
--
分析索引
SQL> exec dbms_stats.gather_index_stats(ownname => 'crm2',indname => 'IDX_ADM_PERMISSION_PID_MID',estimate_percent => '10',degree => '4') ;
pl/sql procedure successfully completed
--
如果发现执行计划走错,删除表的统计信息
SQL>dbms_stats.delete_table_stats(ownname => 'scott',tabname => 'work_list') ;
pl/sql procedure successfully completed
--
导入表的历史统计信息
sql> exec dbms_stats.import_table_stats(ownname => 'scott',tabname => 'work_list',stattab => 'stat_table') ;
pl/sql procedure successfully completed
--
如果进行分析后,大部分表的执行计划都走错,需要导回整个scheme的统计信息
sql> exec dbms_stats.import_schema_stats(ownname => 'scott',stattab => 'stat_table');
pl/sql procedure successfully completed
--
导入索引的统计信息
SQL> exec dbms_stats.import_index_stats(ownname => 'crm2',indname => 'IDX_ADM_PERMISSION_PID_MID',stattab => 'stat_table')
--
检查是否导入成功
SQL> select table_name,num_rows,a.blocks,a.last_analyzed from all_tables a where a.table_name='WORK_LIST';
TABLE_NAME NUM_ROWS BLOCKS LAST_ANALYZED
------------------------------ ---------- ---------- -------------
WORK_LIST 4005 186 2007-10-12 15
--恢复旧的统计信息
例如,假设在 5 月 31 日晚上 10:00 开始运行表 REVENUE 上的统计信息收集作业,而随后查询的性能变差。Oracle 保存了原有的统计信息,您可以通过执行以下命令重新获取这些信息:
SQL> exec dbms_stats.restore_table_stats ( 'ARUP', 'REVENUE', '31-MAY-04 10.00.00.000000000 PM -04:00');
此命令恢复到 5 月 31 日晚上 10:00 为止的统计信息,时间信息是以 TIMESTAMP 数据类型提供。这样您就立即还原了由新的统计信息收集程序所作的更改。
--您能够恢复的时间长度是由保留参数所决定的。要查看当前的保留参数,可使用以下查询:
SQL> select DBMS_STATS.GET_STATS_HISTORY_RETENTION from dual;
GET_STATS_HISTORY_RETENTION
---------------------------
                         31
在本示例中表示可以保存相当于 31 天的统计信息,但并不能予以保证。
--要了解统计信息所覆盖到的确切时间和日期,只需使用以下查询:
SQL> select DBMS_STATS.GET_STATS_HISTORY_AVAILABILITY from dual;
GET_STATS_HISTORY_AVAILABILITY
----------------------------------------------------------------
27-10月-08 11.14.20.357622000 下午 +08:00
该查询表明可用的最陈旧统计信息日期为 10 月 27 日下午 11:14。
--您可以通过执行内建的函数将保留时间设为不同的值。例如,要将其设为 45 天,可使用:
SQL> exec DBMS_STATS.ALTER_STATS_HISTORY_RETENTION (45);
叁、analyze dbms_stats 区别
自从Oracle8.1.5引入dbms_stats包,Experts们便推荐使用dbms_stats取代analyze。理由如下
1,dbms_stats
可以并行分析
2,dbms_stats
有自动分析的功能
(alter table monitor )
3,analyze
分析统计信息的不准确
some times
如果想分析整个用户或数据库,还可以采用工具包,可以并行分析:Dbms_utility(8i以前的工具包) Dbms_stats(8i以后提供的工具包),:(以下两个
dbms_stats最常用)
dbms_stats.gather_schema_stats(User,estimate_percent=>100,cascade=> TRUE);
dbms_stats.gather_table_stats(User,TableName,degree => 4,cascade => true);
总结:
1
DBMS_STATS的优点
a) 可以并行进行,对多个用户,多个Table
b)
可以得到整个分区表的数据和单个分区的数据。

c)
可以在不同级别上Compute Statistics:单个分区,子分区,全表,所有分区
d)
可以倒出统计信息
e)
可以用户自动收集统计信息
f)
对于分区表,建议使用DBMS_STATS,而不是使用Analyze语句
g)
对于oracle 9里面的External TableAnalyze不能使用,只能使用DBMS_STATS来收集信息
2
DBMS_STATS的缺点
a) 不能Validate Structure
b)
不能收集CHAINED ROWS, 不能收集CLUSTER TABLE的信息,这两个仍旧需要使用Analyze语句

c) DBMS_STATS
默认不对索引进行Analyze,因为默认CascadeFalse,需要手工指定为True
五、应用一例:
1、按用户分析
BEGIN                                                                         
DBMS_STATS.GATHER_SCHEMA_STATS(OWNNAME=>   'SCOTT'   ,   CASCADE=>   TRUE);  
END ;                  
2、单表分析
ANALYZE   TABLE   MYTABLE   COMPUTE   STATISTICS;         
获取分析语句:
SELECT   'ANALYZE   TABLE   '||TABLE_NAME||'   COMPUTE   STATISTICS;' FROM   USER_TABLES;         
3、用途举例:
select a.table_name, a.num_rows from user_tables a where a.num_rows = 0;
--统计记录数据为空的表,如果事先未进行数据分析,则统计结果可能会不正确      

阅读(709) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-10-14 17:10:34

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com