本文将与您分享oracle表片段的排序和分析。边肖觉得挺实用的,所以分享给大家学习。希望你看完这篇文章能有所收获。我们就不多说了。让我们和边肖一起看看。
在数据库的日常使用中,由于不断的插入、删除和更新操作,不可避免地会出现表和索引碎片化的情况。如果碎片多,sql的执行效率自然会很差。原因很简单。高水位线(HWL)下的很多数据块没有数据,但是高水位线的数据块在扫描整个表的时候要扫描!
表的碎片不同于文件系统的碎片。当一个表上的DML操作越来越多的时候,HWM之前可能有大量的空闲空间,在读取表的时候,会读入HWM以下的块,这样会产生更多的IO,从而影响性能。只有DDL操作会导致表收缩。
要对表进行碎片整理,有:1种碎片整理方法,使用alter MOVE表,然后重建索引;2.使用alter table启用行移动;然后alter table收缩空间级联(收缩用途有限,所以要注意);3、通过创建表格XXX作为从abb选择*的方式;4.使用导出和导入表;
实验如下:
SQL从dba_objects中将表t1创建为select *;Table created.SQL select count(*) from t1; COUNT(*)---------- 86956SQL insert into t1 select * from t1;86956 rows created.SQL commit;http://
SQL从dba_tables中选择OWNER、TABLE_NAME、TABLE_NAME、NUM_ROWS、BLOCKS、EMPTY_BLOCKS、AVG_SPACE、AVG_ROW_LEN、LAST_ANALYZED,其中TABLE _ NAME=' T1
所有者表名表空间名行数块空块AVG空间AVG行最后分析Commit complete.SQL
SYSTEM
SQL> COL SEGMENT_NAME FOR A15
SQL> select OWNER,SEGMENT_NAME,TABLESPACE_NAME,BYTES,BLOCKS,EXTENTS from dba_segments where segment_name in ('T1','IDX_T1_ID');
OWNER SEGMENT_NAME TABLESPACE_NAME BYTES BLOCKS EXTENTS
------------------------------ --------------- ------------------------------ ---------- ---------- ----------
SYS T1 SYSTEM 20971520 2560 35
SYS IDX_T1_ID SYSTEM 4194304 512 19
可以看到dba_segment中已经可以记录表大小,而dba_tables则没有。
--使用dbms_stats手机统计信息
SQL> exec dbms_stats.gather_table_stats('SYS','T1',CASCADE=>TRUE);
PL/SQL procedure successfully completed.
SQL>
SQL> select OWNER,TABLE_NAME,TABLESPACE_NAME,NUM_ROWS,BLOCKS,EMPTY_BLOCKS,AVG_SPACE,AVG_ROW_LEN,LAST_ANALYZED from dba_tables where TABLE_NAME='T1';
OWNER TABLE_NAME TABLESPACE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE AVG_ROW_LEN LAST_ANALYZED
------------------------------ --------------- --------------- ---------- ---------- ------------ ---------- ----------- -------------------
SYS T1 SYSTEM 173912 2476 0 0 98 2017-10-26 05:35:37
SQL> select OWNER,SEGMENT_NAME,TABLESPACE_NAME,BYTES,BLOCKS,EXTENTS from dba_segments where segment_name in ('T1','IDX_T1_ID');
OWNER SEGMENT_NAME TABLESPACE_NAME BYTES BLOCKS EXTENTS
------------------------------ --------------- --------------- ---------- ---------- ----------
SYS T1 SYSTEM 20971520 2560 35
SYS IDX_T1_ID SYSTEM 4194304 512 19
发现dba_table中已有记录BLOCKS块大小记录,但是没有empty_blocks空块记录和AVG_SPACE值。
--需要使用analyze子句收集表t1的空块信息。
DBMS_STATS包无法获取EMPTY_BLOCKS统计信息,所以需要用analyze命令再收集一次统计信息
SQL> analyze table t1 compute statistics;
Table analyzed.
SQL> select OWNER,TABLE_NAME,TABLESPACE_NAME,NUM_ROWS,BLOCKS,EMPTY_BLOCKS,AVG_SPACE,AVG_ROW_LEN,LAST_ANALYZED from dba_tables where TABLE_NAME='T1';
OWNER TABLE_NAME TABLESPACE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE AVG_ROW_LEN LAST_ANALYZED
------------------------------ --------------- --------------- ---------- ---------- ------------ ---------- ----------- -------------------
SYS T1 SYSTEM 173912 2476 83 863 101 2017-10-26 05:38:18
SQL> select OWNER,SEGMENT_NAME,TABLESPACE_NAME,BYTES,BLOCKS,EXTENTS from dba_segments where segment_name in ('T1','IDX_T1_ID');
OWNER SEGMENT_NAME TABLESPACE_NAME BYTES BLOCKS EXTENTS
------------------------------ --------------- --------------- ---------- ---------- ----------
SYS T1 SYSTEM 20971520 2560 35
SYS IDX_T1_ID SYSTEM 4194304 512 19
发现dba_tables中的 EMPTY_BLOCKS AVG_SPACE AVG_ROW_LEN字段有值了,且AVG_ROW_LEN的值发生了变化。
--计算表在高水位线下还有多少空间可用,这个值应当越低越好,表使用率越接近高水位线,全表扫描所做的无用功也就越少,如下:
SQL> select table_name, (blocks * 8192 / 1024 / 1024) - (num_rows * avg_row_len / 1024 / 1024) "data lower than hwm in mb" from user_tables where table_name = 'T1';
TABLE_NAME data lower than hwm in mb
--------------- -------------------------
T1 2.59235382
查看执行计划,全表扫描大概需要消耗CPU 675
SQL> explain plan for select * from t1;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------
Plan hash value: 3617692013
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 173K| 16M| 675 (1)| 00:00:09 |
| 1 | TABLE ACCESS FULL| T1 | 173K| 16M| 675 (1)| 00:00:09 |
--------------------------------------------------------------------------
8 rows selected.
--删除大部分数据,收集统计信息,全表扫描依然耗cpu 673,如下:
SQL> select count(*) from t1;
COUNT(*)
----------
173912
SQL> delete t1 where rownum <170000;
169999 rows deleted.
SQL> select count(*) from t1;
COUNT(*)
----------
3913
--使用dbms_stats分析表
SQL> exec dbms_stats.gather_table_stats('SYS','T1',CASCADE=>TRUE);
PL/SQL procedure successfully completed.
--再次查询dba_segments和dba_tables视图
SQL> select OWNER,TABLE_NAME,TABLESPACE_NAME,NUM_ROWS,BLOCKS,EMPTY_BLOCKS,AVG_SPACE,AVG_ROW_LEN,LAST_ANALYZED from dba_tables where TABLE_NAME='T1';
OWNER TABLE_NAME TABLESPACE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE AVG_ROW_LEN LAST_ANALYZED
------------------------------ --------------- --------------- ---------- ---------- ------------ ---------- ----------- -------------------
SYS T1 SYSTEM 3913 2476 83 863 101 2017-10-26 05:50:29
SQL> select OWNER,SEGMENT_NAME,TABLESPACE_NAME,BYTES,BLOCKS,EXTENTS from dba_segments where segment_name in ('T1','IDX_T1_ID');
OWNER SEGMENT_NAME TABLESPACE_NAME BYTES BLOCKS EXTENTS
------------------------------ --------------- --------------- ---------- ---------- ----------
SYS T1 SYSTEM 20971520 2560 35
SYS IDX_T1_ID SYSTEM 4194304 512 19
发现dba_tables中的num_rows字段已经更新了,其他字段没有更新;而dba_segments视图相关字段也没有变化。这说明DML操作的删除行操作,即使进行了统计信息的更新,但是因为表里存在碎片,所以表大小没有变化。
--使用analyze分析表:
SQL> analyze table t1 compute statistics;
Table analyzed.
SQL> select OWNER,TABLE_NAME,TABLESPACE_NAME,NUM_ROWS,BLOCKS,EMPTY_BLOCKS,AVG_SPACE,AVG_ROW_LEN,LAST_ANALYZED from dba_tables where TABLE_NAME='T1';
OWNER TABLE_NAME TABLESPACE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE AVG_ROW_LEN LAST_ANALYZED
------------------------------ --------------- --------------- ---------- ---------- ------------ ---------- ----------- -------------------
SYS T1 SYSTEM 3913 2476 83 7761 104 2017-10-26 05:52:00
SQL> select OWNER,SEGMENT_NAME,TABLESPACE_NAME,BYTES,BLOCKS,EXTENTS from dba_segments where segment_name in ('T1','IDX_T1_ID');
OWNER SEGMENT_NAME TABLESPACE_NAME BYTES BLOCKS EXTENTS
------------------------------ --------------- --------------- ---------- ---------- ----------
SYS T1 SYSTEM 20971520 2560 35
SYS IDX_T1_ID SYSTEM 4194304 512 19
还是没有变化,结论如上。。。。。。。。。。。。。。。。。
--查看执行计划,cpu cost 673几乎没变化
SQL> explain plan for select * from t1;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------
Plan hash value: 3617692013
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3913 | 397K| 673 (1)| 00:00:09 |
| 1 | TABLE ACCESS FULL| T1 | 3913 | 397K| 673 (1)| 00:00:09 |
--------------------------------------------------------------------------
8 rows selected.
--再次估算表在高水位线下还有多少空间是无数据的,但在全表扫描时又需要做无用功的数据块,如下:
SQL> select table_name, (blocks * 8192 / 1024 / 1024) - (num_rows * avg_row_len / 1024 / 1024) "data lower than hwm in mb" from user_tables where table_name = 'T1';
TABLE_NAME data lower than hwm in mb
--------------- -------------------------
T1 18.9556503
发现表中碎片增长很多。。。。。。。。。。。。
--对表进行碎片整理,重新收集统计信息,如下:
注:碎片整理方法有:1,使用alter MOVE 表,然后索引rebuild;2.使用alter table enable row movement;然后alter table shrink space cascade(shrink使用有限制,需注意);3,通过 create table XXX as select * from abb; 4,使用导出和导入表 ;
SQL> alter table t1 disable row movement;
Table altered.
SQL> alter table t1 move;
Table altered.
SQL> select INDEX_NAME,STATUS from dba_indexes where index_name ='IDX_T1_ID';
INDEX_NAME STATUS
------------------------------ --------
IDX_T1_ID UNUSABLE
SQL> alter index IDX_T1_ID rebuild online;
Index altered.
--先查询dba_tables/dba_segments:
SQL> select OWNER,TABLE_NAME,TABLESPACE_NAME,NUM_ROWS,BLOCKS,EMPTY_BLOCKS,AVG_SPACE,AVG_ROW_LEN,LAST_ANALYZED from dba_tables where TABLE_NAME='T1';
OWNER TABLE_NAME TABLESPACE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE AVG_ROW_LEN LAST_ANALYZED
------------------------------ --------------- --------------- ---------- ---------- ------------ ---------- ----------- -------------------
SYS T1 SYSTEM 3913 2476 83 7761 104 2017-10-26 05:52:00
SQL> select OWNER,SEGMENT_NAME,TABLESPACE_NAME,BYTES,BLOCKS,EXTENTS from dba_segments where segment_name in ('T1','IDX_T1_ID');
OWNER SEGMENT_NAME TABLESPACE_NAME BYTES BLOCKS EXTENTS
------------------------------ --------------- --------------- ---------- ---------- ----------
SYS T1 SYSTEM 524288 64 8
SYS IDX_T1_ID SYSTEM 131072 16 2
发现经过碎片整理后且在没有收集统计信息的情况下dba_segments的块大小已经自动更新了,而dba_tables各字段没有更新
--再次查询碎片情况:
SQL> select table_name, (blocks * 8192 / 1024 / 1024) - (num_rows * avg_row_len / 1024 / 1024) "data lower than hwm in mb" from user_tables where table_name = 'T1';
TABLE_NAME data lower than hwm in mb
--------------- -------------------------
T1 18.9556503
没有变化。
--收集统计信息,使用dbms_stat包:
SQL> exec dbms_stats.gather_table_stats('SYS','T1',CASCADE=>TRUE);
PL/SQL procedure successfully completed.
SQL>
SQL> select OWNER,TABLE_NAME,TABLESPACE_NAME,NUM_ROWS,BLOCKS,EMPTY_BLOCKS,AVG_SPACE,AVG_ROW_LEN,LAST_ANALYZED from dba_tables where TABLE_NAME='T1';
OWNER TABLE_NAME TABLESPACE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE AVG_ROW_LEN LAST_ANALYZED
------------------------------ --------------- --------------- ---------- ---------- ------------ ---------- ----------- -------------------
SYS T1 SYSTEM 3913 58 83 7761 101 2017-10-26 06:07:17
SQL> select OWNER,SEGMENT_NAME,TABLESPACE_NAME,BYTES,BLOCKS,EXTENTS from dba_segments where segment_name in ('T1','IDX_T1_ID');
OWNER SEGMENT_NAME TABLESPACE_NAME BYTES BLOCKS EXTENTS
------------------------------ --------------- --------------- ---------- ---------- ----------
SYS T1 SYSTEM 524288 64 8
SYS IDX_T1_ID SYSTEM 131072 16 2
SQL> select table_name, (blocks * 8192 / 1024 / 1024) - (num_rows * avg_row_len / 1024 / 1024) "data lower than hwm in mb" from user_tables where table_name = 'T1';
TABLE_NAME data lower than hwm in mb
--------------- -------------------------
T1 .076220512
发现经过dbms_stat包收集统计信息后dba_tables的blocks、AVG_ROW_LEN字段已经更新,且高水位下的碎片已经回收了,但是EMPTY_BLOCKS、AVG_SPACE字段没有更新
--使用analyze子句收集EMPTY_BLOCKS字段统计信息,如下;
SQL> analyze table t1 compute statistics;
Table analyzed.
SQL> select OWNER,TABLE_NAME,TABLESPACE_NAME,NUM_ROWS,BLOCKS,EMPTY_BLOCKS,AVG_SPACE,AVG_ROW_LEN,LAST_ANALYZED from dba_tables where TABLE_NAME='T1';
OWNER TABLE_NAME TABLESPACE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE AVG_ROW_LEN LAST_ANALYZED
------------------------------ --------------- --------------- ---------- ---------- ------------ ---------- ----------- -------------------
SYS T1 SYSTEM 3913 58 5 887 104 2017-10-26 06:10:06
SQL> select OWNER,SEGMENT_NAME,TABLESPACE_NAME,BYTES,BLOCKS,EXTENTS from dba_segments where segment_name in ('T1','IDX_T1_ID');
OWNER SEGMENT_NAME TABLESPACE_NAME BYTES BLOCKS EXTENTS
------------------------------ --------------- --------------- ---------- ---------- ----------
SYS T1 SYSTEM 524288 64 8
SYS IDX_T1_ID SYSTEM 131072 16 2
SQL> select table_name, (blocks * 8192 / 1024 / 1024) - (num_rows * avg_row_len / 1024 / 1024) "data lower than hwm in mb" from user_tables where table_name = 'T1';
TABLE_NAME data lower than hwm in mb
--------------- -------------------------
T1 .06502533
发现经过analyze子句收集统计信息后dba_tables的EMPTY_BLOCKS、AVG_SPACE字段更新了
--再次执行sql,发现CPU cost只有17,如下:
SQL> explain plan for select * from t1;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------
Plan hash value: 3617692013
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3913 | 397K| 17 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| T1 | 3913 | 397K| 17 (0)| 00:00:01 |
--------------------------------------------------------------------------
8 rows selected.
以上就是oracle表碎片的整理分析,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注行业资讯频道。
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/84796.html