一、产生原因:

表产生大量碎片,是因为在delete引起的。delete 删除表并没有回收高水位线
查询表碎片化程度的查语句:
–查找碎片化程度较高的表
SELECT * FROM (
SELECT
TABLE_NAME,
(BLOCKS8192/1024/1024) AS HWH_MB, --已占用大小(高水位线)
(NUM_ROWS
AVG_ROW_LEN/1024/1024) AS USED_MB , --实际大小
ROUND((NUM_ROWSAVG_ROW_LEN/1024/1024)/(BLOCKS8192/1024/1024),3) AS USED_RATE --实际使用率
FROM USER_TABLES WHERE BLOCKS >0
)
WHERE USED_RATE <0.3 (使用率不到30%)

二:演示步骤

1.创建表并插入数据

(1)创建表
create table T3(id int, major varchar(255));

(2)创建插入数据的存储过程 插入100万条数据
CREATE OR REPLACE PROCEDURE P_INSERT_T3 AS
I INT DEFAULT 1;
BEGIN
FOR I IN 1 … 1000000 LOOP
INSERT INTO T3 (ID, MAJOR) VALUES (I, ‘金融学院-’ || I);
END LOOP;
COMMIT;
END;
(3)调用存储过程,插入1亿条数据
BEGIN
P_INSERT_T3;
END;
(4)同时建立索引
create index idx_T3_id on T3( id);

(5)统计表T3的信息
这里的CDM表示用户名 ,T3表示表名
BEGIN
dbms_stats.gather_table_stats(‘CDM’,‘T3’,CASCADE=>TRUE);
END;
analyze table T3 compute statistics;

(6)查看表的数据信息
6.1查询表使用的块、空块、行数
SELECT blocks, empty_blocks, num_rows FROM user_tables WHERE table_name =‘T3’;
– blocks 4150
– empty_blocks 74
– num_rows 1000000

6.2查看表段大小
select sum(bytes)/1024/1024 from USER_segments where segment_name=‘T3’; --33m

6.3 查看表的索引段大小
select sum(bytes)/1024/1024 from USER_segments where segment_name=‘IDX_T3_ID’; --18m

6.4查询表的空间使用情况

SELECT

TABLE_NAME,

(BLOCKS * 8192 / 1024 / 1024) “高水位空间MB”,

(NUM_ROWS * AVG_ROW_LEN / 1024 / 1024) “已用空间MB”,

blocks10/1008192/1024/1024 “预留空间MB(pctfree)”,

(BLOCKS * 8192 / 1024 / 1024)-(NUM_ROWS * AVG_ROW_LEN / 1024 / 1024)-(blocks10/1008192/1024/1024) “浪费空间MB”

FROM USER_TABLES

WHERE table_name = ‘T3’;

information_schema 表碎片 oracle表碎片_删除表


(7)执行执行计划,查看查询语句的CPU消耗情况

explain plan for select * from T3 ;

commit;

select * from table(dbms_xplan.display);

information_schema 表碎片 oracle表碎片_数据库_02

2.删除表之后

(1).删除表:
delete from T3 where id>3000;
commit;
select count(*) from T3; --3000
(2)统计表信息并查看
–执行删除操作之后分析表
BEGIN
dbms_stats.gather_table_stats(‘CDM’,‘T3’,CASCADE=>TRUE);
END;
analyze table T3 compute statistics;

–执行下面语句发现,已使用的块和空块都没有变少,跟删除之前一样,只是行数变少了
SELECT blocks, empty_blocks, num_rows FROM user_tables WHERE table_name =‘T3’;
– blocks 4150
– empty_blocks 74
– num_rows 3000

–执行下面语句发现,高水位线还是跟之前一致,已用空间变少了,但是浪费的空间变多了

SELECT

TABLE_NAME,

(BLOCKS * 8192 / 1024 / 1024) “高水位空间MB”,

(NUM_ROWS * AVG_ROW_LEN / 1024 / 1024) “已用空间MB”,

blocks10/1008192/1024/1024 “预留空间MB(pctfree)”,

(BLOCKS * 8192 / 1024 / 1024)-(NUM_ROWS * AVG_ROW_LEN / 1024 / 1024)-(blocks10/1008192/1024/1024) “浪费空间MB”

FROM USER_TABLES

WHERE table_name = ‘T3’;

information_schema 表碎片 oracle表碎片_执行计划_03


(3)查看执行计划的消耗

–删除表之后查看执行计划消耗 经过查实,与删表之前的消耗资源是一样的

explain plan for select * from T3 ;

commit;

select * from table(dbms_xplan.display);

information_schema 表碎片 oracle表碎片_数据库_04

3.表碎片整理的步骤

进行表的碎片整理
alter table T3 enable row movement; --开启行移动执行shrink之前, 必须开启行移动
alter table T3 shrink space cascade; --收缩表
alter table T3 disable row movement; --关闭行移动

4.碎片整理后查看表的信息

(1)统计分析表的信息
BEGIN
dbms_stats.gather_table_stats(‘CDM’,‘T3’,CASCADE=>TRUE);
END;
analyze table T3 compute statistics;

(2)查看表使用的块大小
select blocks,empty_blocks,num_rows from user_tables where table_name=‘T3’;
– blocks 11
– empty_blocks 5
– num_rows 3000

(3)查看表使用的段大小
select sum(bytes)/1024/1024 from user_segments where segment_name=‘T3’; --0.125
select sum(bytes)/1024/1024 from user_segments where segment_name=‘IDX_T1_ID’ --0.125

(4)查看表水位线和占用空间

–高水位线明显变小了, 浪费空间也变小了

SELECT

TABLE_NAME,

(BLOCKS * 8192 / 1024 / 1024) “高水位空间MB”,

(NUM_ROWS * AVG_ROW_LEN / 1024 / 1024) “已用空间MB”,

blocks10/1008192/1024/1024 “预留空间MB(pctfree)”,

(BLOCKS * 8192 / 1024 / 1024)-(NUM_ROWS * AVG_ROW_LEN / 1024 / 1024)-(blocks10/1008192/1024/1024) “浪费空间MB”

FROM USER_TABLES

WHERE table_name = ‘T3’;

information_schema 表碎片 oracle表碎片_sql_05


(5)查看执行计划的消耗:

查看消耗很少,同时可以看到,经过shrink 碎片整理,所以也没有丢失

explain plan for select * from T3 where id=1001 ;

commit;

select * from table(dbms_xplan.display);

information_schema 表碎片 oracle表碎片_oracle_06