您的位置:首页 > 数据库

数据库性能优化、统计信息与对象统计信息概述收集、扩展统计信息、dbms_stats.get_prefs

2014-09-16 22:08 459 查看
数据库性能优化

相关书籍:

1.基于成本的Oracle优化法则

2.Oracle性能诊断艺术

3.基于Oracle的SQL优化

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

两种优化器:

CBO cost-base optimizer

基于cost 更大适应性/灵活性/10g开始

RBO rule-base optimizer

基于规则 制定了15条/10g以前

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

统计信息:

1.系统统计信息

cpu、I/O

exec dbms_stats.gather_system_stats;

2.数据库对象统计信息

表、索引、列、扩展

exec dbms_stats.gather_table_stats('TEST_USER1','TEST_1');

--收集表的统计信息(同时会级联收集索引和列的统计信息)

exec dbms_stats.gather_table_stats('TEST_USER1','TEST_1',cascade=>false);

--不会联机收集索引和列的统计信息

exec dbms_stats.gather_index_stats('TEST_USER1','INDEX_NAME');

--收集索引的统计信息

alter table table_name enable row movement;

--允许表的行迁移

alter table table_name shrink space;

--降低表的高水位线

exec dbms_stats.gather_database_stats;

--收集整个数据库的统计信息

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

直方图

扩展统计信息



query rewrite 查询重写

星形转换

视图合并

为此前推

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

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

1,统计信息概述

统计信息是oracle CBO计算候选执行计划的cost的基础。因此,获取准确的统计信息,

是oracle能够选择最优执行计划(cost最低)的首要条件。

在oracle 9i的时候,oracle只计算每个执行计划的I/O成本,并将其作为评价执行计划好坏的依据。

从10g开始,oracle将sql执行中消耗的cpu资源,也作为成本计入执行计划的成本计算。

因此,一个执行计划的cost值,包含了cpu和I/O两种资源的成本。

与统计信息相关的几个初始化参数

SQL> show parameter statistics;

NAME TYPE VALUE

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

optimizer_use_pending_statistics boolean FALSE

statistics_level string TYPICAL

timed_os_statistics integer 0

timed_statistics boolean TRUE

optimizer_use_pending_statistics:

显示CBO是否使用pending状态的统计信息。

一般情况下,我们收集完统计信息,则oracle会默认将新收集到的统计信息置于publish状态,这样CBO可以随时使用。

我们可以使用dbms_stats.DELETE_PENDING_STATS删除处于pending状态的统计信息,也可以使用

dbms_stat.set_*_prefs来设置统计信息是否处于publish状态。

timed_statistics

是否收集与时间相关的统计信息。例如cpu和elapsed times。

如果STATISTICS_LEVEL设置为TYPICAL或者ALL, 则该参数的默认值为true;

如果STATISTICS_LEVEL设置为BASIC, 则该参数的默认值为false。

从11.1.0.7.0开始,如果STATISTICS_LEVEL设置为TYPICAL或者ALL,该参数不能被设置为false。

timed_os_statistics

该参数指定了当从客户端生成一个请求,或者完成一个请求的时候,收集系统统计信息的时间间隔(单位为s)。这又分了两种情况:

dedicated 模式

在用户登录和后继客户端通过OCI调用从而作为一个远程过程调用信息进入oracle server时,oracle收集系统统计信息。

shared 模式

在客户端调用oracle完成时,oracle收集系统统计信息。

如果STATISTICS_LEVEL设置为ALL, 则该参数默认值为5;

如果STATISTICS_LEVEL设置为BASIC或者TYPICAL, 则该参数默认值为0。

需要注意的是,收集系统统计信息是相当消耗系统资源的活动。oracle强烈建议你在完成系统统计信息收集之后,立即将该参数修改为0。

statistics_level

控制收集统计信息的级别,有三个参数值:

BASIC :收集基本的统计信息

TYPICAL:收集大部分统计信息(数据库的默认设置)

ALL:收集全部统计信息,除了收集typical模式下的所有统计信息之外,还将收集基于时间的os统计信息和执行计划的统计信息。

(执行计划的统计信息包括什么)

如果将默认值typical改为basic,则将停止收集如下对象的统计信息:

Automatic Workload Repository (AWR) Snapshots

Automatic Database Diagnostic Monitor (ADDM)

All server-generated alerts

Automatic SGA Memory Management

Automatic optimizer statistics collection

Object level statistics

End to End Application Tracing (V$CLIENT_STATS)

Database time distribution statistics (V$SESS_TIME_MODEL and V$SYS_TIME_MODEL)

Service level statistics

Buffer cache advisory

MTTR advisory

Shared pool sizing advisory

Segment level statistics

PGA Target advisory

Timed statistics

Monitoring of statistics

可以用如下sql来查看oracle目前收集哪些对象的统计信息:

select * from v$statistics_level

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

1.1 系统统计信息

除了收集数据库中所有对象的统计信息以外,oracle也可以收集数据库所在主机的统计信息,也就是os级别的统计信息。

这包括主机的cpu性能(频率),系统I/O的吞吐量等。但是,在默认情况下,oracle不会自动的收集系统统计信息。

因此,当完成数据库在服务器主机上的安装配置之后,可以考虑手动收集系统级别的统计信息。

另外,在数据库主机进行硬件升级之后,尤其是是I/O系统进行了重大升级之后,也应该再次手动收集系统级别的统计信息。

可以用如下的命令来手工完成系统统计信息的收集:

SQL> exec dbms_stats.gather_system_stats;

PL/SQL procedure successfully completed

SQL> select * from sys.aux_stats$;

SNAME PNAME PVAL1 PVAL2

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

SYSSTATS_INFO STATUS COMPLETED

SYSSTATS_INFO DSTART 06-13-2014 16:52

SYSSTATS_INFO DSTOP 06-13-2014 16:52

SYSSTATS_INFO FLAGS 1

SYSSTATS_MAIN CPUSPEEDNW 1504

SYSSTATS_MAIN IOSEEKTIM 2

SYSSTATS_MAIN IOTFRSPEED 4096

SYSSTATS_MAIN SREADTIM

SYSSTATS_MAIN MREADTIM

SYSSTATS_MAIN CPUSPEED

SYSSTATS_MAIN MBRC

SYSSTATS_MAIN MAXTHR

SYSSTATS_MAIN SLAVETHR

13 rows selected

该过程中的gathering_mode参数可以用来指定收集系统统计信息的模式:

NOWORKLOAD: 无工作负载模式,用于收集系统I/O部分的统计信息。

INTERVAL: 收集某一指定时间间隔内的统计信息。

START | STOP:手动收集一段时间内的统计信息。

在12c中,又引入了EXADATA模式,用来收集类似于exadata这样具有高I/O吞吐量和吞吐能力的系统统计信息。

注:关于该过程所有参数的详细描述,请参考Oracle Database PL/SQL Packages and Types Reference 12c Release 1 (12.1)第153章。

1.2 数据库对象统计信息

除了系统级别的统计信息,oracle还会收集数据库中对象的统计信息。

不同于系统级别的统计信息,oracle默认会自动收集数据库对象的统计信息。

1.2.1 自动收集统计信息

详情参见统计信息自动收集.txt

1.2.1.1部分特例

在11g及以前版本中,创建索引的时候,由于需要进行全表扫描,因此此时Oracle顺便完成了索引的统计信息收集。而创建表时,则没有类似的动作。

在12c中,当用直接路径加载数据,例如create table as select (CTAS)和insert as select(IAS)时,Oracle也顺便搭载了统计信息

的收集工作。这就意味着,在采用这样的方式加载数据之后,不需要额外的全表扫描来收集统计信息了。

1.2.2 手动收集统计信息

1.2.2.1 DBMS_STATS相关过程

oracle的DBMS_STATS包提供了如下收集计信息的过程:

GATHER_DATABASE_STATS; 收集数据库中所有对象的统计信息

GATHER_DICTIONARY_STATS; 收集'SYS','SYSTEM'和RDBMS组件对象的统计信息

GATHER_FIXED_OBJECTS_STATS; 收集所有动态性能表的统计信息

GATHER_INDEX_STATS; 收集索引的统计信息

GATHER_PROCESSING_RATE;

GATHER_SCHEMA_STATS; 收集某一用户的所有对象的统计信息

GATHER_SYSTEM_STATS; 收集系统统计信息

GATHER_TABLE_STATS; 收集表的统计信息

1.2.2.2 统计信息内容

其中,表、列、索引统计信息分别包含如下内容:

表统计信息(user_tables/all_tables/dba_tables):

NUM_ROWS 记录行数

BLOCKS 高水位线以下的数据块数

EMPTY_BLOCKS 高水位线以上数据块数,dbms_stat不统计.

AVG_SPACE 平均空闲空间,不统计

CHAIN_CNT 行迁移行数,不统计

注:本记录实际上会记录发生行迁移或者行链接现象的所有行数,但是dbms_stats中的任意收集统计信息的过程都不处理这些信息,而只是简单的将该值置为0.可以使用

ANALYZE TABLE orders LIST CHAINED ROWS INTO chained_rows;

来获取关于行迁移和行链接的相关信息。其中chained_rows 可以通过

$ORACLE_HOME/rdbms/admin/utlchain.sql脚本来创建。

AVG_ROW_LEN 行平均长度

列统计信息(user_tab_columns):

NUM_DISTINCT 唯一值数量

LOW_VALUE 该列最小值

HIGH_VALUE 该列最大值

DENSITY 表示该列数据的重复率,0到1的小数,越接近0表示重复率越低。

NUM_NULLS 该列null值的数量

AVG_COL_LEN 列平均长度,以字节为单位

HISTOGRAM 是否有直方图统计信息,

none: 没有

frequency: 频率直方图

height balanced 高度直方图

NUM_BUCKETS 直方图桶数

索引统计信息(user_indexes):

BLEVEL 索引的深度,也就是层数

LEAF_BLOCKS 叶子块数目

DISTINCT_KEYS 索引distinct键值数目

AVG_LEAF_BLOCKS_PER_KEY 每一个键值的平均叶子块数目

AVG_DATA_BLOCKS_PER_KEY 每一个键值的平均数据块数目

CLUSTERING_FACTOR 簇聚因子 (反映行与索引键值的有序性)

注:统计信息包括但不局限于以上内容。

1.2.2.3 扩展统计信息

在数据库中,oracle默认同一个表的不同列之间,它们的关系是相互独立的。

也就是说,某一列的取值,不会影响到其他列的取值,也不会受到其他列取值的影响。

而在实际当中,往往会存在取值互相影响或者制约的列之间的关系。

比如我们有一个雇员表,其中一列为出生月份,另外一列为星座。显然这两列之间,是存在一定关系的。

为处理这样的问题,oracle引入了扩展统计信息(extension statistics)的概念。

在oracle中,此处的扩展,指的是列的组合,或者是基于列的表达式。

有如下的例子:

HR@ORCL> alter table hr.employees no flashback archive;

HR@ORCL> select dbms_stats.create_extended_stats('hr','employees','(first_name,last_name,job_id)') from dual;

HR@ORCL> exec dbms_stats.gather_table_stats('hr','employees',method_opt=>'for all columns size 1,for columns (first_name,last_name,job_id) size auto');

HR@ORCL> select * from user_stat_extensions where table_name='EMPLOYEES';

注:扩展统计信息中的列组,与复合索引;

扩展统计信息中的基于列的表达式,与函数索引

它们在影响执行计划的时候有何不同?

另注:自动收集统计信息时,不会收集扩展统计信息。

1.2.2.4 estimate_percent参数分析

GATHER_DATABASE_STATS

GATHER_DICTIONARY_STATS

GATHER_INDEX_STATS

GATHER_SCHEMA_STATS

GATHER_TABLE_STATS

以上五个收集统计信息的过程,都包含了estimate_percent这个参数。

在12.1的官方文档中,oracle对该参数的解释如下:

该参数指定了在收集统计信息时对行采样的百分比(NULL表示全部采样)。其可用值的范围为【0.000001,100】。

可以使用常量DBMS_STATS.AUTO_SAMPLE_SIZE来让oracle自己决定采取适当的数值来收集统计信息。这也是默认行为。

该默认值可以通过

SET_DATABASE_PREFS,

SET_GLOBAL_PREFS,

SET_SCHEMA_PREFS,

SET_TABLE_PREFS进行修改。

注:在设置这些默认项之后,也会作用于统计信息的自动收集。

可以使用dbms_stats.get_prefs获取当前系统与统计信息相关的参数的默认值。

可以获取的参数包括

■ AUTOSTATS_TARGET

■ CASCADE

■ CONCURRENT

■ DEGREE

■ ESTIMATE_PERCENT

■ METHOD_OPT

■ NO_INVALIDATE

■ GRANULARITY

■ PUBLISH

■ INCREMENTAL

■ INCREMENTAL_LEVEL

■ INCREMENTAL_STALENESS

■ STALE_PERCENT

■ GLOBAL_TEMP_TABLE_STATS

■ TABLE_CACHED_BLOCKS

■ OPTIONS

其中,

get_prefs用于获取全局的统计信息收集配置选项。

要获取对象级别的统计信息配置选项:

SELECT * FROM DBA_TAB_STAT_PREFS;

例子如下:

SQL> select dbms_stats.get_prefs('estimate_percent') name from dual;

NAME

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

DBMS_STATS.AUTO_SAMPLE_SIZE

按照oracle的解释,AUTO_SAMPLE_SIZE为一个常量,其值可以通过如下方式获取:

Connected to Oracle Database 12c Enterprise Edition Release 12.1.0.1.0

Connected as sys@ORCL AS SYSDBA

SQL> create table t_val (name varchar2(30),value number);

Table created

SQL> begin

2 insert into t_val values ('AUTO_SAMPLE_SIZE',DBMS_STATS.AUTO_SAMPLE_SIZE);

3 end;

4 /

PL/SQL procedure successfully completed

SQL> select * from t_val;

NAME VALUE

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

AUTO_SAMPLE_SIZE 0

显然这不是我们想要的值。

按照oracle的说明,该值的取值范围,也应该在【0.000001,100】之间。

我们可以设计一个实验,来获取该值的一个近似值。

SQL> create table t as select * from dba_objects;

Table created

SQL> set timing on;

SQL> exec dbms_stats.gather_table_stats(ownname => 'SYS',tabname => 'T',estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE);

PL/SQL procedure successfully completed

Executed in 0.608 seconds

SQL> exec dbms_stats.gather_table_stats(ownname => 'SYS',tabname => 'T',estimate_percent => NULL);

PL/SQL procedure successfully completed

Executed in 0.999 seconds

SQL> exec dbms_stats.gather_table_stats(ownname => 'SYS',tabname => 'T',estimate_percent => 100);

PL/SQL procedure successfully completed

Executed in 0.889 seconds

SQL> exec dbms_stats.gather_table_stats(ownname => 'SYS',tabname => 'T',estimate_percent => 50);

PL/SQL procedure successfully completed

Executed in 0.483 seconds

SQL> exec dbms_stats.gather_table_stats(ownname => 'SYS',tabname => 'T');

PL/SQL procedure successfully completed

Executed in 0.234 seconds

SQL> exec dbms_stats.gather_table_stats(ownname => 'SYS',tabname => 'T',estimate_percent => 60);

PL/SQL procedure successfully completed

Executed in 0.577 seconds

SQL> exec dbms_stats.gather_table_stats(ownname => 'SYS',tabname => 'T',estimate_percent => 62);

PL/SQL procedure successfully completed

Executed in 0.593 seconds

SQL> exec dbms_stats.gather_table_stats(ownname => 'SYS',tabname => 'T',estimate_percent => 65);

PL/SQL procedure successfully completed

Executed in 0.608 seconds

SQL> set timing off;

由上述实验可知,estimate_percent 设置为null时,为全部采样,也就是100。

当将其设置为其默认值DBMS_STATS.AUTO_SAMPLE_SIZE时,收集统计信息消耗的时间与将其设置为65时相同。

鉴于本实验是在12.1的数据库中测试,所以我们基本可以断定:

在12.1中,estimate_percent的默认采样比例,大致在65%。

1.2.2.5 统计信息锁定与force选项

为预防由于统计信息不规则变化影响执行计划,我们可以选择锁定某些对象的统计信息。

oracle提供了如下锁定统计信息的过程:

LOCK_PARTITION_STATS

LOCK_SCHEMA_STATS

LOCK_TABLE_STATS

对应的,也有如下解除锁定的过程:

UNLOCK_PARTITION_STATS

UNLOCK_SCHEMA_STATS

UNLOCK_TABLE_STATS

我们以前面测试estimate_percent中创建的测试表T为例,显示表统计信息的锁定与解锁问题。

SQL> exec dbms_stats.lock_table_stats(ownname => 'SYS',tabname => 'T');

PL/SQL procedure successfully completed

SQL> desc dba_tab_statistics;

Name Type Nullable Default Comments

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

OWNER VARCHAR2(128) Y Owner of the object

TABLE_NAME VARCHAR2(128) Y Name of the table

PARTITION_NAME VARCHAR2(128) Y Name of the partition

PARTITION_POSITION NUMBER Y Position of the partition within table

SUBPARTITION_NAME VARCHAR2(128) Y Name of the subpartition

SUBPARTITION_POSITION NUMBER Y Position of the subpartition within partition

OBJECT_TYPE VARCHAR2(12) Y Type of the object (TABLE, PARTITION, SUBPARTITION)

NUM_ROWS NUMBER Y The number of rows in the object

BLOCKS NUMBER Y The number of used blocks in the object

EMPTY_BLOCKS NUMBER Y The number of empty blocks in the object

AVG_SPACE NUMBER Y The average available free space in the object

CHAIN_CNT NUMBER Y The number of chained rows in the object

AVG_ROW_LEN NUMBER Y The average row length, including row overhead

AVG_SPACE_FREELIST_BLOCKS NUMBER Y The average freespace of all blocks on a freelist

NUM_FREELIST_BLOCKS NUMBER Y The number of blocks on the freelist

AVG_CACHED_BLOCKS NUMBER Y Average number of blocks in buffer cache

AVG_CACHE_HIT_RATIO NUMBER Y Average cache hit ratio for the object

SAMPLE_SIZE NUMBER Y The sample size used in analyzing this table

LAST_ANALYZED DATE Y The date of the most recent time this table was analyzed

GLOBAL_STATS VARCHAR2(3) Y Are the statistics calculated without merging underlying partitions?

USER_STATS VARCHAR2(3) Y Were the statistics entered directly by the user?

STATTYPE_LOCKED VARCHAR2(5) Y type of statistics lock

STALE_STATS VARCHAR2(3) Y Whether statistics for the object is stale or not

SCOPE VARCHAR2(7) Y whether statistics for the object is shared or session

SQL> col OWNER for a20

SQL> col TABLE_NAME for a20

SQL> col STATTYPE_LOCKED for a20

SQL> select OWNER,TABLE_NAME,STATTYPE_LOCKED from dba_tab_statistics where TABLE_NAME='T';

OWNER TABLE_NAME STATTYPE_LOCKED

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

SYS T ALL

在T表的统计信息被锁定之后,是否可以重新搜集该表的统计信息呢?

SQL> exec dbms_stats.gather_table_stats(ownname => 'SYS',tabname => 'T');

begin dbms_stats.gather_table_stats(ownname => 'SYS',tabname => 'T'); end;

ORA-20005: object statistics are locked (stattype = ALL)

ORA-06512: 在 "SYS.DBMS_STATS", line 33859

ORA-06512: 在 line 2

显示该统计信息已经被锁定。

我们此处可以用force参数强制收集。

SQL> exec dbms_stats.gather_table_stats(ownname => 'SYS',tabname => 'T',force => true);

PL/SQL procedure successfully completed

强制收集之后,该统计信息依然处于锁定状态:

SQL> select OWNER,TABLE_NAME,STATTYPE_LOCKED from dba_tab_statistics where TABLE_NAME='T';

OWNER TABLE_NAME STATTYPE_LOCKED

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

SYS T ALL

下次再次收集,依然会报错:

SQL> exec dbms_stats.gather_table_stats(ownname => 'SYS',tabname => 'T');

begin dbms_stats.gather_table_stats(ownname => 'SYS',tabname => 'T'); end;

ORA-20005: object statistics are locked (stattype = ALL)

ORA-06512: 在 "SYS.DBMS_STATS", line 33859

ORA-06512: 在 line 2

我们可以解锁该统计信息:

SQL> exec dbms_stats.unlock_table_stats(ownname => 'SYS',tabname => 'T');

PL/SQL procedure successfully completed

SQL> select OWNER,TABLE_NAME,STATTYPE_LOCKED from dba_tab_statistics where TABLE_NAME='T';

OWNER TABLE_NAME STATTYPE_LOCKED

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

SYS T

这样即便不指定force参数,也可以重新收集统计信息了。

SQL> exec dbms_stats.gather_table_stats(ownname => 'SYS',tabname => 'T');

PL/SQL procedure successfully completed

1.2.2.6 用户自定义统计信息表

当我们需要导出存储在系统字典表中的统计信息,

或者打算利用统计信息做一些测试而不影响存储在系统字典表中的统计信息时,

我们就可以创建用户自定义的统计信息表,从而来存储统计信息。

1.2.2.7 12c性能优化白皮书
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: