最近有朋友问到了DBMS_SPACE包的使用,也看了一下,大部分是关于dbms_space.space_usage的使用,space_usage这个过程的例子已经很多了,我也就不再多说了,除了这个过程外,另外还有两个过程也有着特殊的用处,但使用的人不多,我们也来看看这两个过程有什么用。

这两个过程为:CREATE_INDEX_COST和CREATE_TABLE_COST,分别用户评估创建索引和创建表的存储开销(空间占用情况)。

CREATE_INDEX_COST的语法如下:

DBMS_SPACE.CREATE_INDEX_COST (

ddl            IN   VARCHAR2,

used_bytes     OUT  NUMBER,

alloc_bytes    OUT  NUMBER,

plan_table     IN   VARCHAR2 DEFAULT NULL);

下面是相关的测试代码

1、准备相关表和数据

SQL> set serveroutput on

SQL> create table t(c char(100),d varchar2(200));

表已创建。

SQL> begin

2   for i in 1..5000 loop

3    insert into t values(i,i);

4   end loop;

5   commit;

6 end;

7 /

PL/SQL过程已成功完成。

2、分析表,注意:没有统计信息,CREATE_INDEX_COST将无法计算索引的存储开销

SQL> analyze table t compute statistics;

表已分析。

SQL> declare

2   v1 number;

3   v2 number;

4 begin

5   DBMS_SPACE.CREATE_INDEX_COST('create index i on t(c)',v1,v2);

6   dbms_output.put_line(v1/1024||' '||v2/1024);

7 end;

8 /

488.28125 640   --计算出的索引将占用488K字节空间,为该索引需要分配640k存储空间

PL/SQL过程已成功完成。

3、创建实际索引,确定索引存储空间是否与计算的结果相符

SQL> create index i on t(c);

索引已创建。

SQL> select count(*) from user_extents where segment_name='I';

COUNT(*)

----------

11

已选择1行。 --11个64k的区,比计算出的大1个区

4、再次装载数据

SQL> begin

2   for i in 1..5000 loop

3    insert into t values(i,i);

4   end loop;

5   commit;

6 end;

7 /

PL/SQL过程已成功完成。

SQL> declare

2   v1 number;

3   v2 number;

4 begin

5   DBMS_SPACE.CREATE_INDEX_COST('create index i on t(c)',v1,v2);

6   dbms_output.put_line(v1/1024||' '||v2/1024);

7 end;

8 /

488.28125 640          --没有分析之前,获得得仍然是根据以前分析结果计算的值

PL/SQL过程已成功完成。

SQL> analyze table t compute statistics;

表已分析。

SQL> declare

2   v1 number;

3   v2 number;

4 begin

5   DBMS_SPACE.CREATE_INDEX_COST('create index i on t(c)',v1,v2);

6   dbms_output.put_line(v1/1024||' '||v2/1024);

7 end;

8 /

976.5625 2048                 --分析之后,得到新的结果

PL/SQL过程已成功完成。

5、再次验证,16个64k的区和1个1024k的区,2048k,与估计值相同

SQL> select count(*) from user_extents where segment_name='I';

COUNT(*)

----------

17

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

6、换了一个字段进行测试

SQL> declare

2   v1 number;

3   v2 number;

4 begin

5   DBMS_SPACE.CREATE_INDEX_COST('create index i on t(d)',v1,v2);

6   dbms_output.put_line(v1/1024||' '||v2/1024);

7 end;

8 /

39.0625 192       --计算出的索引将占用39K字节空间,为该索引需要分配192k存储空间

PL/SQL过程已成功完成。

7、创建索引,新建的索引比估算的值大1个区

SQL> create index i on t(d);

索引已创建。

SQL> select count(*) from user_extents where segment_name='I';

COUNT(*)

----------

4

SQL> drop index i;

8、再次装载数据并分析表

SQL> begin

2   for i in 1..10000 loop

3    insert into t values(i,i);

4   end loop;

5   commit;

6 end;

7 /

PL/SQL过程已成功完成。

SQL> analyze table t compute statistics;

表已分析。

9、重新计算,得到新的估算值

SQL> declare

2   v1 number;

3   v2 number;

4 begin

5   DBMS_SPACE.CREATE_INDEX_COST('create index i on t(d)',v1,v2);

6   dbms_output.put_line(v1/1024||' '||v2/1024);

7 end;

8 /

78.125 320

PL/SQL过程已成功完成。

10、创建索引,新建的索引比估计的大2个区

SQL> create index i on t(d);

索引已创建。

SQL> select count(*) from user_extents where segment_name='I';

COUNT(*)

----------

7

11、顺便测试shink space的效果

SQL> select count(*) from t;

COUNT(*)

----------

20000

SQL> delete t where rownum<=15000;

已删除15000行。

SQL> commit;

提交完成。

SQL> alter table t enable row movement;

表已更改。

12、在删掉15000行数据后,没有整理空间之前进行统计信息收集

SQL> analyze table t compute statistics;

表已分析。

SQL> declare

2   v1 number;

3   v2 number;

4 begin

5   DBMS_SPACE.CREATE_INDEX_COST('create index i on t(d)',v1,v2);

6   dbms_output.put_line(v1/1024||' '||v2/1024);

7 end;

8 /

24.4140625 128         --基于新收集的统计信息计算,估算的索引需要分配128k存储空间

PL/SQL过程已成功完成。

13、收缩表,释放占用的存储空间

SQL> alter table t shrink space;

表已更改。

SQL> analyze table t compute statistics;

表已分析。

SQL> declare

2   v1 number;

3   v2 number;

4 begin

5   DBMS_SPACE.CREATE_INDEX_COST('create index i on t(d)',v1,v2);

6   dbms_output.put_line(v1/1024||' '||v2/1024);

7 end;

8 /

24.4140625 128  --收缩后重新收集统计信息,与原统计信息一样,因此计算出的大小一样

PL/SQL过程已成功完成。

SQL> select count(*) from user_extents where segment_name='I';

COUNT(*)

----------

7

--现有索引并没有收缩,仅仅是表空间进行了收缩,因此现有索引仍保持原大小

14、重建索引,对比新的索引大小与计算出的索引大小一样大

SQL> alter index i rebuild;

索引已更改。

SQL> select count(*) from user_extents where segment_name='I';

COUNT(*)

----------

2

--重建索引后新的索引占用空间与计算出的空间一样大

CREATE_TABLE_COST有两种用法,因此包内进行了overload,具体的语法如下:

DBMS_SPACE.CREATE_TABLE_COST (

tablespace_name   IN VARCHAR2,

avg_row_size      IN NUMBER,

row_count         IN NUMBER,

pct_free          IN NUMBER,

used_bytes        OUT NUMBER,

alloc_bytes       OUT NUMBER);

DBMS_SPACE.CREATE_TABLE_COST (

tablespace_name   IN VARCHAR2,

colinfos          IN CREATE_TABLE_COST_COLUMNS,

row_count         IN NUMBER,

pct_free          IN NUMBER,

used_bytes        OUT NUMBER,

alloc_bytes       OUT NUMBER);

CREATE TYPE create_table_cost_colinfo IS OBJECT (

COL_TYPE  VARCHAR(200),

COL_SIZE  NUMBER);

下面是关于CREATE_TABLE_COST的测试代码

1、测试创建一个表所需的存储大小,预计该表平均行长度为100字节,10000行数据

SQL> DECLARE

2   V1 NUMBER;

3   V2 NUMBER;

4 BEGIN

5   DBMS_SPACE.CREATE_TABLE_COST('USERS', 100, 10000, 10, V1, V2);

6   DBMS_OUTPUT.PUT_LINE('V1: '||V1/1024/8||' V2: '||V2/1024/8);

7 END;

8 /

V1: 143 V2: 256         --估算出该表需要存储空间143块,所需分配空间256块

PL/SQL过程已成功完成。

2、创建该表,并插入10000行数据

SQL> CREATE TABLE T1(C CHAR(96));         --96字节的char字段平均行长度为100字节

表已创建。

SQL> BEGIN

2   FOR I IN 1..10000 LOOP

3    INSERT INTO T1 VALUES(I);

4   ENDLOOP;

5   COMMIT;

6 END;

7 /

PL/SQL过程已成功完成。

3、分析表统计信息

SQL> ANALYZE TABLE T1 COMPUTE STATISTICS;

表已分析。

SQL> SELECT BLOCKS,EMPTY_BLOCKS,AVG_ROW_LEN

FROM USER_TABLES WHERE TABLE_NAME='T1';

BLOCKS EMPTY_BLOCKS AVG_ROW_LEN

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

180          76        100

--经检查,高水平线之前的块数180块,高水平线之后的空块数76块,总存储空间为256块,与DBMS_SPACE.CREATE_INDEX_COST计算出的总需要存储空间大小相符。

4、通过dbms_space.space_usage过程,可以进一步看到表中各个块的使用情况

declare

unf number;

unfb number;

fs1 number;

fs1b number;

fs2 number;

fs2b number;

fs3 number;

fs3b number;

fs4 number;

fs4b number;

full number;

fullb number;

own dba_tables.owner%type;

tab dba_tables.table_name%type;

yesno varchar2(3);

type parts is table of dba_tab_partitions%rowtype;

partlist parts;

type cursor_ref is ref cursor;

c_cur cursor_ref;

begin

own:=upper('&owner');

tab:=upper('&table_name');

dbms_output.put_line('--------------------------------------------------------------------------------');

open c_cur for select partitioned from dba_tables

where wner=own and table_name=tab;

fetch c_cur into yesno;

close c_cur;

dbms_output.put_line('Owner:    '||own);

dbms_output.put_line('Table:    '||tab);

dbms_output.put_line('------------------------------------------------');

if yesno='NO' then

dbms_space.space_usage(own,tab,'TABLE',unf,unfb,fs1,fs1b,fs2,fs2b,fs3,fs3b,fs4,fs4b,full,fullb);

dbms_output.put_line('unf: '||unf||' fs1: '||fs1||' fs2: '||fs2||' fs3: '||fs3||' fs4: '||fs4||' full: '||full);

else

open c_cur for select * from dba_tab_partitions

where table_owner=own and table_name=tab;

fetch c_cur bulk collect into partlist;

close c_cur;

for i in partlist.first .. partlist.last   loop

dbms_space.space_usage(partlist(i).table_owner,partlist(i).table_name,'TABLE

PARTITION',unf,unfb,fs1,fs1b,fs2,fs2b,fs3,fs3b,fs4,fs4b,full,fullb,partlist(i).partition_name);

dbms_output.put_line('Partition: '||partlist(i).partition_name);

dbms_output.put_line('unf: '||unf||' fs1: '||fs1||' fs2: '||fs2||' fs3: '||fs3||' fs4: '||fs4||' full: '||full);

end loop;

end if;

dbms_output.put_line('--------------------------------------------------------------------------------');

end;

/

输入owner的值: HR

原值  22:  own:=upper('&owner');

新值  22:  own:=upper('HR');

输入table_name的值: T1

原值  23:  tab:=upper('&table_name');

新值  23:  tab:=upper('T1');

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

Owner:    HR

Table:    T1

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

unf: 0 fs1: 1 fs2: 0 fs3: 0 fs4: 39 full: 140

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

PL/SQL过程已成功完成。

--经查看,发现该表写满数据的块有140块,3/4满的块有39块,1/4满的块有1块,该表存储空间没有有效利用,可以看到140+39+1=180,这些均为高水平线之下的块。但与DBMS_SPACE.CREATE_INDEX_COST计算出的数据需要143块不符。

5、对表进行空间整理并重新分析

SQL> ALTER TABLE T1 MOVE;

表已更改。

SQL> ANALYZE TABLE T1 COMPUTE STATISTICS;

表已分析。

SQL> SELECT BLOCKS,EMPTY_BLOCKS,AVG_ROW_LEN

FROM USER_TABLES WHERE TABLE_NAME='T1';

BLOCKS EMPTY_BLOCKS AVG_ROW_LEN

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

155         101        100

--经检查,高水平线之前的块数155,高水平线之后的空块数101,平均行长度100字节

6、通过dbms_space.space_usage过程,可以进一步看到表中各个块的使用情况

declare

unf number;

unfb number;

fs1 number;

fs1b number;

fs2 number;

fs2b number;

fs3 number;

fs3b number;

fs4 number;

fs4b number;

full number;

fullb number;

own dba_tables.owner%type;

tab dba_tables.table_name%type;

yesno varchar2(3);

type parts is table of dba_tab_partitions%rowtype;

partlist parts;

type cursor_ref is ref cursor;

c_cur cursor_ref;

begin

own:=upper('&owner');

tab:=upper('&table_name');

dbms_output.put_line('--------------------------------------------------------------------------------');

open c_cur for select partitioned from dba_tables

where wner=own and table_name=tab;

fetch c_cur into yesno;

close c_cur;

dbms_output.put_line('Owner:    '||own);

dbms_output.put_line('Table:    '||tab);

dbms_output.put_line('------------------------------------------------');

if yesno='NO' then

dbms_space.space_usage(own,tab,'TABLE',unf,unfb,fs1,fs1b,fs2,fs2b,fs3,fs3b,fs4,fs4b,full,fullb);

dbms_output.put_line('unf: '||unf||' fs1: '||fs1||' fs2: '||fs2||' fs3: '||fs3||' fs4: '||fs4||' full: '||full);

else

open c_cur for select * from dba_tab_partitions

where table_owner=own and table_name=tab;

fetch c_cur bulk collect into partlist;

close c_cur;

for i in partlist.first .. partlist.last   loop

dbms_space.space_usage(partlist(i).table_owner,partlist(i).table_name,'TABLE

PARTITION',unf,unfb,fs1,fs1b,fs2,fs2b,fs3,fs3b,fs4,fs4b,full,fullb,partlist(i).partition_name);

dbms_output.put_line('Partition: '||partlist(i).partition_name);

dbms_output.put_line('unf: '||unf||' fs1: '||fs1||' fs2: '||fs2||' fs3: '||fs3||' fs4: '||fs4||' full: '||full);

end loop;

end if;

dbms_output.put_line('--------------------------------------------------------------------------------');

end;

/

输入owner的值: HR

原值  22:  own:=upper('&owner');

新值  22:  own:=upper('HR');

输入table_name的值: T1

原值  23:  tab:=upper('&table_name');

新值  23:  tab:=upper('T1');

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

Owner:    HR

Table:    T1

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

unf: 0 fs1: 0 fs2: 0 fs3: 0 fs4: 0 full: 143

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

PL/SQL过程已成功完成。

--经查看,发现该表写满数据的块有143块,与DBMS_SPACE.CREATE_INDEX_COST计算出的数据需要块数完全相同

-- review the parameters

SELECT argument_name, data_type, type_owner, type_name

FROM all_arguments

WHERE object_name = 'CREATE_TABLE_COST'

AND verload = 2

-- examine the input parameter type

SELECT text

FROM dba_source

WHERE name = 'CREATE_TABLE_COST_COLUMNS';

-- drill down further into the input parameter type

SELECT text

FROM dba_source

WHERE name = 'create_table_cost_colinfo';

set serveroutput on

DECLARE

ub NUMBER;

ab NUMBER;

cl sys.create_table_cost_columns;

BEGIN

cl := sys.create_table_cost_columns( sys.create_table_cost_colinfo('NUMBER',10),

sys.create_table_cost_colinfo('VARCHAR2',30),

sys.create_table_cost_colinfo('VARCHAR2',30),

sys.create_table_cost_colinfo('DATE',NULL));

DBMS_SPACE.CREATE_TABLE_COST('SYSTEM',cl,100000,0,ub,ab);

DBMS_OUTPUT.PUT_LINE('Used Bytes: ' || TO_CHAR(ub));

DBMS_OUTPUT.PUT_LINE('Alloc Bytes: ' || TO_CHAR(ab));

END;

/

http://blog.csdn.net/liqfyiyi/article/details/7036838

DBMS_SPACE包的使用的更多相关文章

  1. 十五、dbms_space(分析段增长和空间的需求)

    1.概述 作用:用于分析段增长和空间的需求. 2.包的组成 1).unused_space作用:用于返回对象(表.索引.簇)的未用空间语法:dbms_space.unused_space(segmen ...

  2. Npm包的开发

    个人开发包的目录结构 ├── coverage //istanbul测试覆盖率生成的文件 ├── index.js //入口文件 ├── introduce.md //说明文件 ├── lib │   ...

  3. Windows server 2012 添加中文语言包(英文转为中文)(离线)

    Windows server 2012 添加中文语言包(英文转为中文)(离线) 相关资料: 公司环境:亚马孙aws虚拟机 英文版Windows2012 中文SQL Server2012安装包,需要安装 ...

  4. 如何在nuget上传自己的包+搭建自己公司的NuGet服务器(新方法)

    运维相关:http://www.cnblogs.com/dunitian/p/4822808.html#iis 先注册一个nuget账号https://www.nuget.org/ 下载并安装一下Nu ...

  5. android http 抓包

    有时候想开发的时候想看APP发出的http请求和响应是什么,这就需要抓包了,这可以得到一些不为人知的api,比如还可以干些“坏事”... 需要工具: Fiddler2 抓包(点击下载) Android ...

  6. 带你实现开发者头条APP(四)---首页优化(加入design包)

    title: 带你实现开发者头条APP(四)---首页优化(加入design包) tags: design,Toolbar,TabLayout,RecyclerView grammar_cjkRuby ...

  7. git克隆项目到本地&&全局安装依赖项目&&安装依赖包&&启动服务

     一.安装本地开发环境 1.安装本项目 在需要保存到本地的项目的文件夹,进入到文件夹里点击右键,bash here,出现下图: 2.安装依赖项目  3.安装依赖包(进入到命令行) # 安装依赖包 $ ...

  8. 关于Visual Studio 未能加载各种Package包的解决方案

    问题: 打开Visual Studio 的时候,总提示未能加载相应的Package包,有时候还无法打开项目,各种提示 解决方案: 进入用户目录 C:\Users\用户名\AppData\Local\M ...

  9. VS项目中使用Nuget还原包后编译生产还一直报错?

    Nuget官网下载Nuget项目包的命令地址:https://www.nuget.org/packages 今天就遇到一个比较奇葩的问题,折腾了很久终于搞定了: 问题是这样的:我的解决方案原本是好好的 ...

随机推荐

  1. Android动态逆向分析工具ZjDroid--脱壳神器

    项目地址:https://github.com/BaiduSecurityLabs/ZjDroid 前提条件: 1.Root手机一部 2.须要通过Xposed installer( http://dl ...

  2. C#实现对数据库的备份还原(完全)

    C#实现对数据库的备份还原 ( 用SQL语句实现对数据库备份还原操作 备份SqlServer数据库: backup database 数据库名 to disk (备份文件存放路径+文件名).bak 还 ...

  3. spring:按照Bean的名称自动装配User

    本实例将介绍如何按照Bean 的名称自动装配 User 对象! <bean> 元素的 autowire 属性负责自动装配 <bean> 标签,定义 JavaBean 的属性.这 ...

  4. 辨异 —— Java 中 String 的相等性比较

    How do I compare strings in Java? 1. 语法知识 ==:判断的是引用的相等性(reference equality),也即是否为同一对象: .equals():判断的 ...

  5. codevs1519 过路费(最小生成树+LCA)

    1519 过路费  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 大师 Master     题目描述 Description 在某个遥远的国家里,有 n个城市.编号为 1,2 ...

  6. mysql行列转置

    --创建行转列表及插入数据 create table tb_RowConvertToColumn ( username nvarchar(100) null, course nvarchar(100) ...

  7. Java.Cas4.0客户端接入配置

    1.本示例中使用cas4.0+cas-client-core3.4版本,ide则是myeclipse2014 blue版本,mvn使用3.9版本 2.注意事项:请先实现破解cas-client-cor ...

  8. CDN 内容分发网络

    第一步,HTML的文件引用:HTML的文件头(也有文件中,文件尾)那边常有其他文件引用,比如CSS以及JS的引用. 就以bootstrap常用的引用来举个栗子你常见的引用可能会是这样的: <he ...

  9. CSS的常用属性(三)

    静态定位 position: static (默认) 标准流 绝对定位 position: absolute 特点: 元素使用绝对定位之后,不占据原来的位置(脱标) 元素使用绝对定位,位置是从浏览器出 ...

  10. php加密方法有哪些

    1. MD5加密 string md5 ( string $str [, bool $raw_output = false ] ) 参数 str -- 原始字符串. raw_output -- 如果可 ...