① 搜集和删除索引、表和簇的统计信息
② 验证表、索引和簇的结构
③ 鉴定表和簇和行迁移和行链接
针对analyze的搜集和删除统计信息功能而言
Oracle推荐使用DBMS_STATS包来代替analyze搜集优化信息
DBMS_STATS可以并行的搜集信息,可以搜集分区表的全局信息
进一步来说,CBO只会使用DBMS_STATS包所统计出来的信息 https://blog.csdn.net/iteye_14608/article/details/82447870
analyze table table_name compute statistics;
2、收集表的统计信息,并且以计算模式
analyze table table_name compute statistics for table;
3、以计算模式收集索引的统计信息
analyze index index_name compute statistics;
4、以计算模式对表的列收集统计信息
analyze table table_name compute statistics for table for columns col1,col2;
4、删除表、表的所有列及表的所有索引的统计信息
analyze table table_name delete statistics;
不要用analyze的compute 和estimate收集优化统计信息,analyze命令已经过时,一般用dbms_stats 来收集优化统计信息,dbms_stats命令可以使用parallel,对分区对象收集全局统计信息, fine tune your statistics collection in other ways. 基于成本的优化器取决于统计信息
analyze命令收集的统计信息和基于成本优化器所需统计信息无关,下列情况用analyze比dbms_stats要好:
2、 什么情况下用analyze命令
(1) 收集或者删除索引,分区索引,表,分区表,cluster的统计信息,
analyze收集表的统计信息都放在 all_tables dba_tables user_tables 表里面了,表里的统计信息是指 NUM_ROWS、BLOCKS 、EMPTY_BLOCKS 、AVG_SPACE、CHAIN_COUNT、AVG_ROW_LEN
analyze table有如下限制: 你不能收集数据字典的统计信息
你不能收集 external table的统计信息,但是可以用dbms_stats收集
analyze 不能收集临时表的默认统计信息
你不能compute or estimate , REF column types, varrays, nested tables, LOB column types 类型的统计信息
analyze 收集索引里的统计信息 都放在 USER_INDEXES 、dba_indexes 、ALL_INDEXES表里,表里的统计信息指BLEVEL、LEAF_BLOCKS、DISTINCT_KEYS、AVG_LEAF_BLOCKS_PER_KEY、AVG_DATA_BLOCKS_PER_KEY、CLUSTERING_FACTOR
cluster 的统计信息都放在 ALL_CLUSTERS,USER_CLUSTERS, andDBA_CLUSTERS
(2)验证索引,分区索引,表,分区表 索引组织表 对象的结构
(3)确定表和cluster 的行连接或者迁移
3什么情况下用dbms_stats命令
一般用dbms_stats 来收集优化统计信息,dbms_stats命令可以使用parallel,对分区对象收集全局统计信息, fine tune your statistics collection in other ways. 基于成本的优化器取决于统计信息
GATHER_INDEX_STATS
GATHER_TABLE_STATS
GATHER_SCHEMA_STATS
GATHER_DATABASE_STATS
4 analyze语法
ANALYZE
{ { TABLE [ schema. ] table
| INDEX [ schema. ] index
} [ partition_extension_clause ]
| CLUSTER [ schema. ] cluster
}
{ validation_clauses
| LIST CHAINED ROWS [ into_clause ]
| DELETE [ SYSTEM ] STATISTICS
} ;
当我们收集统计信息时,如果表或索引上有大量的数据被删除,那么如果采用compute或者 estimage 来收集,可以会进行full table scan,因此会使用很多的时间
为了验证表,索引,cluster 物化视图的结构完整性,可以 用analyze语句加上validate structure 选项来验证,如果是有效的则不返回错误,如果结构有问题,就是返回错误
指定 VALIDATE REF UPDATE 去验证指定表的ref值,检测每个ref的rowid和它正在的rowid进行比较,如果有必要修改,就会修改,这个语句只能在分析表的时候用
如果一个表的用户对依赖对象没有select权限,那么oracle会认为他们是不合法的,并且设置成null,随后在查询时ref值也不可用,即使对此对象有合适的权限。
ANALYZE TABLE emp VALIDATE STRUCTURE;
VALIDATE STRUCTURE 用来验证分析对象结构的合法性,此统计信息的收集不是给优化器使用
对于表,数据库验证了数据块和行的完整性,对于索引组织表,数据库也会生成主键的压缩统计信息
对于cluster,数据库自动验证cluster table 结构的合理性
对于分区表,数据库也会验证每一行属于正确的分区,如果某行分到不正确的分区,她的rowid就会插入到INVALID_ROWS表中;
对于临时表,数据库会在当前session中检测表和索引的合法性
对于索引,数据库会验证每个索引block 的完整性和block 是否损坏。 这个命令不会确实每个表的row 是否和索引的row 匹配。你可以使用cascade来验证
oracle为每个普通索引计算压缩统计信息,并且存储索引的统计信息到INDEX_STATS andINDEX_HISTOGRAM
ANALYZE TABLE emp VALIDATE STRUCTURE CASCADE;
CASCADE 用来验证表或者cluster以及表或cluster上的相关索引信息的合法性 ,一般cascade会进行一个完整的验证合法性,需要消耗更多的资源
ANALYZE TABLE emp VALIDATE STRUCTURE CASCADE FAST;
FAST 用来检测表上存在的损坏,而不用报告具体损坏的细节,你可以用fast选项确定是否损坏,用cascade不带fast来确定损坏的细节,如果你用此方法验证已经enable的函数索引,那么可能会返回错误,你必须重建索引
ANALYZE TABLE emp VALIDATE STRUCTURE CASCADE ONLINE;
ONLINE选项用来在DML操作正在某个对象时,验证某个对象的合法性,为保证并发性,而降低了验证对象的合法性的性能,当你使用online验证对象的合法性时,不会收集对象的统计信息,当你使用offline的时候回收集统计信息。 你不能使用online分析cluster
OFFLINE :是默认值。当你使用offline的时候,会增加验证对象合法性的性能,但是会阻碍INSERT,UPDATE, and DELETE语句访问对象的并发性,不影响select语句,
INTO 语句仅对分区表有效,数据库会把分区表中不合法行的rowid放到一个表中去,如果你忽略用户模式,会认为指定的表是在当前用户下,如果你忽略用户模式和表,那么会认为是表名为 INVALID_ROWS ,此表的sql脚本是 $ORACLE_HOME/rdbms/admin/utlvalid.sql
create table INVALID_ROWS (
owner_name varchar2(30),
table_name varchar2(30),
partition_name varchar2(30),
subpartition_name varchar2(30),
head_rowid rowid,
analyze_timestamp date
);
ANALYZE CLUSTER emp_dept LIST CHAINED ROWS INTO CHAINED_ROWS;
LIST CHAINED ROWS 可以让你通过分析表和cluster 确定迁移和行连接的行,你不能把这个语句用在分析索引
INTO 语句会把行连接和行迁移的行放到表中,如果你忽略用户模式,会认为指定的表是在当前用户下,如果你忽略用户模式和表,那么会认为是表名为 CHAINED_ROWS,此表必须在你本地的数据库中,创建表的脚本是
ANALYZE TABLE orders DELETE STATISTICS;
DELETE STATISTICS: 能够删除通过分析保存在数据字典里的信息
当你用这个语句可以自动删除定义在表上的索引的统计信息
如果你只想删除系统的统计信息而不删除用户定义的统计信息,可以指定system用户来删除,如果你忽略了system,那么用户定义在的列或者索引的统计信息也会删除
5 、 example
SQL> create table t1 as select *From emp;
表已创建
SQL> select OWNER,TABLE_NAME,STATUS,NUM_ROWS,BLOCKS,EMPTY_BLOCKS,AVG_SPACE,CHAIN_CNT,AVG_ROW_LEN from dba_tables where table_name='T1';
OWNER TABLE STATUS NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE CHAIN_CNT AVG_ROW_LEN
---------- ----- -------- ---------- ---------- ------------ ---------- ---------- -----------
SCOTT T1 VALID
SQL> ANALYZE TABLE T1 COMPUTE STATISTICS;
表已分析。
SQL> select OWNER,TABLE_NAME,STATUS,NUM_ROWS,BLOCKS,EMPTY_BLOCKS,AVG_SPACE,CHAIN_CNT,AVG_ROW_LEN from dba_tables where table_name='T1';
OWNER TABLE STATUS NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE CHAIN_CNT AVG_ROW_LEN
---------- ----- -------- ---------- ---------- ------------ ---------- ---------- -----------
SCOTT T1 VALID 12 4 4 7533 0 41
SQL> ANALYZE TABLE T1 DELETE STATISTICS;
表已分析。
SQL> select OWNER,TABLE_NAME,STATUS,NUM_ROWS,BLOCKS,EMPTY_BLOCKS,AVG_SPACE,CHAIN_CNT,AVG_ROW_LEN from dba_tables where table_name='T1';
OWNER TABLE STATUS NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE CHAIN_CNT AVG_ROW_LEN
---------- ----- -------- ---------- ---------- ------------ ---------- ---------- -----------
SCOTT T1 VALID
SQL> exec dbms_stats.gather_table_stats('SCOTT','T1');
PL/SQL 过程已成功完成。
SQL> select OWNER,TABLE_NAME,STATUS,NUM_ROWS,BLOCKS,EMPTY_BLOCKS,AVG_SPACE,CHAIN_CNT,AVG_ROW_LEN from dba_tables where table_name='T1';
OWNER TABLE STATUS NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE CHAIN_CNT AVG_ROW_LEN
---------- ----- -------- ---------- ---------- ------------ ---------- ---------- -----------
SCOTT T1 VALID 12 4 0 0 0 39
结论:可以发现analyze 可以收集dba_tables 表里的统计信息,而dbms_stats.gather_table_stats 只能收集到 AVG_ROW_LEN
SQL> create unique index ii on t1(empno);
索引已创建。
SQL> select OWNER,INDEX_NAME,INDEX_TYPE,COMPRESSION,BLEVEL,STATUS,NUM_ROWS,DISTINCT_KEYS,LEAF_BLOCKS,DEGREE from dba_indexes where table_name='T1'
OWNER INDEX_NAME INDEX_TYPE COMPRESS BLEVEL STATUS NUM_ROWS DISTINCT_KEYS LEAF_BLOCKS DEGREE
---------- ------------------------------ --------------------------- -------- ---------- -------- ---------- ------------- ----------- ----------
SCOTT II NORMAL DISABLED 0 VALID 12 12 1 1
SQL> ANALYZE TABLE T1 DELETE STATISTICS;
表已分析。
SQL> select OWNER,TABLE_NAME,STATUS,NUM_ROWS,BLOCKS,EMPTY_BLOCKS,AVG_SPACE,CHAIN_CNT,AVG_ROW_LEN from dba_tables where table_name='T1';
OWNER TABLE STATUS NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE CHAIN_CNT AVG_ROW_LEN
---------- ----- -------- ---------- ---------- ------------ ---------- ---------- -----------
SCOTT T1 VALID
结论:删除表上的统计信息,那么定义在此表上的索引的统计信息也一起删除
SQL> analyze table t1 validate structure cascade;
表已分析。
SQL> select OWNER,TABLE_NAME,STATUS,NUM_ROWS,BLOCKS,EMPTY_BLOCKS,AVG_SPACE,CHAIN_CNT,AVG_ROW_LEN from dba_tables where table_name='T1';
OWNER TABLE STATUS NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE CHAIN_CNT AVG_ROW_LEN
---------- ----- -------- ---------- ---------- ------------ ---------- ---------- -----------
SCOTT T1 VALID
结论:分析表结构的时候,不会收集统计信息
SQL> analyze table t1 list chained rows ;
analyze table t1 list chained rows
*
第 1 行出现错误:
ORA-01495: 未找到指定的链接行表
SQL> @?/rdbms/admin/utlchain.sql
表已创建。
SQL> Analyze table t1 list chained rows;
表已分析。
SQL> select *From CHAINED_ROWS;
未选定行
结论:如果不指定表名,那么必须手动创建默认的表 CHAINED_ROWS
SQL> drop table t1 purge;
表已删除。
SQL> create table t1 as select *From emp;
表已创建。
SQL> create index ii on t1(empno);
索引已创建。
SQL> select *From V$OBJECT_USAGE
2 ;
未选定行
SQL> alter index ii monitoring usage;
索引已更改。
SQL> analyze table t1 compute statistics;
表已分析。
SQL> alter index ii monitoring usage;
索引已更改。
SQL> select *From V$OBJECT_USAGE
2 ;
INDEX_NAME TABLE MON USE START_MONITORING END_MONITORING
------------------------------ ----- --- --- ------------------- -------------------
II T1 YES NO 03/15/2013 15:31:13
SQL> exec dbms_stats.gather_table_stats('SCOTT','T1');
PL/SQL 过程已成功完成。
SQL> select *From V$OBJECT_USAGE ;
INDEX_NAME TABLE MON USE START_MONITORING END_MONITORING
------------------------------ ----- --- --- ------------------- -------------------
II T1 YES NO 03/15/2013 15:31:13
结论:dbms_stats.gather_table_stats 在收集统计信息的时候会收集索引的统计信息,但是analyze在收集统计信息的时候不会收集索引的统计信息,但是我们一定要记住,使用dbms_stats收集的统计信息是给基于成本的优化器使用的,但是analyze 收集的统计信息是 是dba_table 里,analyze 命令可以验证表的结构 validate,可以检查行迁移行连接
ANALYZE - 收集与数据库有关的统计
SYNOPSIS
ANALYZE [ VERBOSE ] [ table [ (column [, ...] ) ] ]
DESCRIPTION 描述
ANALYZE 收集有关 PostgreSQL 表的内容的统计,然后把结果保存在系统表 pg_statistic 里。随后,查询规划器就可以使用这些统计帮助判断查询的最有效的规划。
如果没有参数,ANALYZE 检查在当前数据库里的所有表。 如果有参数,ANALYZE 只检查那个表。 你还可以给出一列字段名字,这个时候只收集那些字段的统计信息。
PARAMETERS 参数
- VERBOSE
-
打开处理过程信息的显示。 - table
-
要分析的特定表(可能用模式名修饰)的名字。缺省是当前数据库里所有表。 - column
-
要分析的特定字段的名字。缺省是所有字段。
OUTPUTS 输出
如果声明了 VERBOSE,ANALYZE 发出进度信息,表明当前正在处理的是哪行。 同时打印有关改表的很多其它信息。
NOTES 注意
周期性地运行 ANALYZE,或者在对表的大部分内容做了更改之后马上运行它是个好习惯, 准确的统计信息将帮助规划器选择最合适的查询规划,并因此而改善查询处理的速度。 一种比较经常采用的策略是每天在低负荷的时候运行一次 VACUUM [vacuum(7)] 和 ANALYZE。
和 VACUUM FULL 不同的是, ANALYZE 只需要在目标表上有一个读取锁, 因此它可以和表上的其它活动并行地运行。
收集的统计信息通常包括一个每字段最常用数值的列表以及一个包线图,显示每个字段里数据的近似分布。 如果 ANALYZE 认为它们都没有什么用, (比如,在一个唯一键字的字段上没有公共的数值)或者是该字段数据类型不支持相关的操作符, 那么它们都可以忽略。在 Chapter 21 ``Routine Database Maintenance'' 中有关于统计的更多信息。
对于大表,ANALYZE 采集表内容的一个随机的抽样做统计,而不是检查每一行。 这样就保证了即使是在很大的表上,我们也只需要很少的一些时间就可以完成分析。 不过,要注意的是统计只是近似的结果,而且每次运行ANALYZE都会导致 EXPLAIN 显示的规划器的预期开销有一些小变化, 即使表内容实际上没有改变也这样。在很小的概率的情况下,这个不确定的行为会导致查询优化器在不同 ANALYZE 之间选择不同的查询规划。为了避免这个问题,可以提高 ANALYZE 收集的统计数量,像下面描述的那样。
分析的广度可以通过用调整 default_statistics_target 参变量, 或者是以每字段为基础通过用 ALTER TABLE ... ALTER COLUMN ... SET STATISTICS (参阅 ALTER TABLE [alter_table(7)]) 设置每字段的统计目标来控制。目标数值设置最常用数值列表中的记录的最大数目以及包线图中的最大块数。 缺省的目标数值是 10,不过我们可以调节这个数值获取规划器计算精度和 ANALYZE 运行所需要的时间以及 pg_statistic 里面占据的空间数目之间的平衡。 特别是,把统计目标设置为零就关闭了该字段的统计收集。 这么做对那些从来不参与到查询的 WHERE,GROUP BY,或者 ORDER BY 子句里的字段是很有用的,因为规划器不会使用到这样的字段上的统计。
在被分析的字段中最大的统计目标决定为统计采样的表中的行的数目。 增大目标会导致做 ANALYZE 的时候成比例地增大对时间和空间的需求。
————————————————
https://blog.csdn.net/wll_1017/article/details/8672227