Chinaunix首页 | 论坛 | 博客
  • 博客访问: 154669
  • 博文数量: 39
  • 博客积分: 825
  • 博客等级: 准尉
  • 技术积分: 955
  • 用 户 组: 普通用户
  • 注册时间: 2012-10-25 14:05
文章分类

全部博文(39)

文章存档

2014年(4)

2013年(13)

2012年(22)

我的朋友

分类: Oracle

2012-11-05 19:39:29

【环境配置】
  延用【最基本的io成本计算法则 】文章中的配置。
  
【建立表空间】  

SELECT tablespace_name, file_name FROM dba_data_files ORDER BY 1;
SELECT dbms_metadata.get_ddl('TABLESPACE', 'USERS') tbs_ddl FROM dual;

ALTER SYSTEM SET db_2k_cache_size=50M;

CREATE TABLESPACE dict_tabs_2k BLOCKSIZE 2k DATAFILE 
'F:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\dict_tabs_2k01.DBF' SIZE 50M
AUTOEXTEND ON UNIFORM SIZE 1M
LOGGING ONLINE PERMANENT
EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT MANUAL;

ALTER SYSTEM SET db_4k_cache_size=50M;

CREATE TABLESPACE dict_tabs_4k BLOCKSIZE 4k DATAFILE 
'F:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\dict_tabs_4k01.DBF' SIZE 50M
AUTOEXTEND ON UNIFORM SIZE 1M
LOGGING ONLINE PERMANENT
EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT MANUAL;

CREATE TABLESPACE dict_tabs DATAFILE 
'F:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\dict_tabs01.DBF' SIZE 100M
AUTOEXTEND ON UNIFORM SIZE 1M
LOGGING ONLINE PERMANENT BLOCKSIZE 8192
EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT MANUAL;


【建表】

CREATE TABLE onew_tab TABLESPACE dict_tabs
PCTFREE 99
PCTUSED 1
  AS
SELECT CAST(LEVEL AS CHAR(20)) AS id1,
       CAST(MOD(LEVEL, 20) AS CHAR(20)) AS id2,
       CAST(MOD(LEVEL, 500) AS CHAR(20)) AS id3
FROM   dual
CONNECT BY LEVEL <= 10000;

CREATE TABLE dict_tabs_2k TABLESPACE dict_tabs_2k
PCTFREE 99
PCTUSED 1
  AS
SELECT CAST(LEVEL AS CHAR(20)) AS id1,
       CAST(MOD(LEVEL, 20) AS CHAR(20)) AS id2,
       CAST(MOD(LEVEL, 500) AS CHAR(20)) AS id3
FROM   dual
CONNECT BY LEVEL <= 10000;

CREATE TABLE dict_tabs_4k TABLESPACE dict_tabs_4k
PCTFREE 99
PCTUSED 1
  AS
SELECT CAST(LEVEL AS CHAR(20)) AS id1,
       CAST(MOD(LEVEL, 20) AS CHAR(20)) AS id2,
       CAST(MOD(LEVEL, 500) AS CHAR(20)) AS id3
FROM   dual
CONNECT BY LEVEL <= 10000;

【收集统计信息】

BEGIN
  dbms_stats.gather_table_stats(ownname          => USER,
                                tabname          => 'onew_tab',
                                estimate_percent => 100,
                                method_opt       => 'for all columns size 1',
                                cascade          => TRUE);
  dbms_stats.gather_table_stats(ownname          => USER,
                                tabname          => 'dict_tabs_2k',
                                estimate_percent => 100,
                                method_opt       => 'for all columns size 1',
                                cascade          => TRUE);
  dbms_stats.gather_table_stats(ownname          => USER,
                                tabname          => 'dict_tabs_4k',
                                estimate_percent => 100,
                                method_opt       => 'for all columns size 1',
                                cascade          => TRUE);
END;
/

【浏览统计信息】

SELECT de.file_id, de.block_id, de.blocks
FROM   dba_extents de
WHERE  de.segment_name = upper('ONEW_TAB');

SELECT utl_raw.cast_to_varchar2(dtcs.low_value) AS lval,
       utl_raw.cast_to_varchar2(dtcs.high_value) AS hval,
       dtcs.histogram,
       dtcs.num_distinct,
       dtcs.density,
       dtcs.num_nulls,
       dtcs.avg_col_len
FROM   dba_tab_col_statistics dtcs
WHERE  dtcs.table_name = 'ONEW_TAB';

SELECT dts.num_rows, dts.blocks, dts.avg_row_len
FROM   dba_tab_statistics dts
WHERE  dts.table_name = 'ONEW_TAB';


【查看cbo成本估算】

DELETE FROM plan_table;
EXPLAIN PLAN SET STATEMENT_ID='8k' FOR SELECT COUNT(*) FROM ONEW_TAB;
EXPLAIN PLAN SET STATEMENT_ID='2k' FOR SELECT COUNT(*) FROM dict_tabs_2k;
EXPLAIN PLAN SET STATEMENT_ID='4k' FOR SELECT COUNT(*) FROM dict_tabs_4k;

SELECT STATEMENT_ID,cpu_cost,io_cost,COST FROM plan_table WHERE ID=0;

/*
STATEMENT_ID CPU_COST IO_COST  COST
2k                  611      611
4k                  963      963
8k                  1519    1519
*/

从前一篇【最基本的io成本计算法则 】中我们知道,最基本的
io_cost成本公式为:

blocks / ( POWER(db_file_multiblock_read_count,0.6581)*1.6765 )

round(10000 / (power(db_file_multiblock_read_count, 0.6581) * 1.6765) + 1)  = 611  --推算出db_file_multiblock_read_count=32
round(10000 / (power(db_file_multiblock_read_count, 0.6581) * 1.6765) + 1)  = 963  --推算出db_file_multiblock_read_count=16

【结论】

从上面的观测中我们得知:对于非标准块大小的表,cbo会以标准块为基准来评估成本,通俗解释如下:
对于本来可以一次性读取8(db_file_multiblock_read_count)个8192(db_block_size)字节个块的系统;
如果表块为2k,则它一次性可以读取32块;
如果表块为4k,则它一次性可以读取16块。

8*8 = 2*32 = 16*4

所以在计算非标准块的io成本时,cbo会偷偷的将db_file_multiblock_read_count修改。
阅读(985) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~