Oracle 数据结构知多少(一)

来源:互联网 发布:游戏耳机品牌 知乎 编辑:程序博客网 时间:2024/04/25 03:02

转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://leonarding.blog.51cto.com/6045525/1173387

 

Oracle 数据结构知多少(一)》
概念篇
这里呢我只是把Oracle逻辑结构和物理结构所涉及到的segment  extent  block块的概念和相互管理简要的说明一下。
Segment段:Oracle内部常叫“段对象”,凡是分配存储空间的对象就叫段对象。既可以自动段空间管理ASSM,又可以手动段空间管理MSSM。段属性依赖于块属性。
Extent区:多个区组成一个段,区是Oracle最小的分配单元,区与区不一定是连续的,区可以分布在不同的数据文件上。
Block块:一片连续的块组成一个区,是Oracle最小的IO单元,最小的操作单元,RMAN备份/恢复最小单元,数据库块是操作系统块的整数倍。
数据I/O:由磁盘与内存之间的通道决定的,而不是由数据怎么分割决定的。分割只是善于管理,I/O方面影响不大。(例如放在一个表空间和放在多个表空间)
一方面I/O通道导致性能下降
一方面latch争用导致性能下降

数据库版本
LEO1@LEO1> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE    11.2.0.1.0      Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production

实验篇
1.查看一个表空间,有多少个extents,多少blocks,多少空余空间。
查看表空间空间使用情况,我想这是100%DBA每天都要做的工作,现在我把自己常用的表空间查询语句测试一下。
LEO1@LEO1> select df.tablespace_name "表空间名",totalspace "总空间M",freespace "剩余空间M",round((1-freespace/totalspace)*100,2) "使用率%"
from
(select tablespace_name,round(sum(bytes)/1024/1024) totalspace from dba_data_files group by tablespace_name) df,
(select tablespace_name,round(sum(bytes)/1024/1024) freespace from dba_free_space group by tablespace_name) fs
where df.tablespace_name=fs.tablespace_name order by df.tablespace_name ;   
表空间名                 总空间M     剩余空间M     使用率%
--------------------------------------------------------------------------------------------------------------------
LEO1                     400           248           38      业务表空间
SYSAUX                   610           38            93.77
SYSTEM                   710           18            97.46
UNDOTBS1                165           134           18.79
UNDOTBS2                100           0             100
USERS                    5             4             20
查看一个表空间,有多少个extents,多少blocks呢?
LEO1@LEO1> select tablespace_name,file_id,extent_id,block_id,blocks from dba_extents where tablespace_name='LEO1' order by extent_id;
TABLESPACE_NAME                   FILE_ID  EXTENT_ID   BLOCK_ID     BLOCKS
------------------------------ ---------- ---------- ---------- ----------
LEO1                                    5         22      39040        128
LEO1                                    5         22      40192        128
LEO1                                    5         22      41344        128
LEO1                                    5         22      42752        128
LEO1                                    5         22       8576        128
LEO1                                    5         22       9216        128
LEO1                                    5         22       3712        128
LEO1                                    5         23       1152        128
LEO1                                    5         23      35456        128
LEO1                                    5         23      36864        128
LEO1                                    5         23      38016        128
LEO1                                    5         23      39168        128
LEO1                                    5         23      40320        128
LEO1                                    5         23      41472        128
LEO1                                    5         23      42880        128
LEO1                                    5         23       8704        128
LEO1                                    5         23       9344        128
LEO1                                    5         23       3840        128
711 rows selected.
这里一共711行,没有都打印出来,我们只把相关几列的含义给大家说明
FILE_IDLEO1表空间对应的数据文件号
EXTENT_ID:这个数据文件里包含了多少个区
BLOCK_ID:每个区起始的数据块号
BLOCKS:每个区包含的数据块数
把上面的参数汇总一下就可以看出一个表空间包含有多少个extents多少blocks了。

2.示例演示通过rowid得到数据块的相关信息(所在对象,文件,数据块)
rowOracle处理数据的最小单位,至少会扫描一行,也是lock的最小单位,不同用户可以修改不同的行,因为是行级锁由ITL事物槽控制。
rowid:我想大家对这个东东应该都不会陌生,说白了就是行的物理磁盘地址,由十六进制表示,由行头和行体组成。
行头:记录行的属性信息方便管理。
行体:记录字段的值,即数据。
下面我们来看看rowid在数据库中是如何表示的
LEO1@LEO1> drop table leo1 purge;                                          清空环境
Table dropped.
LEO1@LEO1> create table leo1 as select * from dba_objects where object_id in (1,2,3);   创建表
Table created.
LEO1@LEO1> select rowid,object_id,object_name from leo1;         表中记录及对应的rowid
ROWID                  OBJECT_ID     OBJECT_NAME
--------------------------------------------------------------------------------
AAASKGAAFAAAAWzAAA    3            I_OBJ#
AAASKGAAFAAAAWzAAB    2            C_OBJ#
我们数了一下rowid18位字符组成,每组字符代表不同的含义,18位最大寻址空间“32G
AAASKG:对象id
AAF:文件id
AAAAWz:块id
AAA:行id
这四部分唯一标识了一行的物理地址,基于rowid的数据查询是最快的,比index还要快
下面我们使用DBMS_ROWID包来得到数据块的相关信息
LEO1@LEO1> select rowid,dbms_rowid.rowid_object(rowid) object_id,
dbms_rowid.rowid_relative_fno(rowid) file_id,
dbms_rowid.rowid_block_number(rowid) block_id,
dbms_rowid.rowid_row_number(rowid) row_id
from leo1;  2    3    4    5  
ROWID                    OBJECT_ID    FILE_ID   BLOCK_ID     ROW_ID
----------------------------------------------------------------------------------------------------------------
AAASKGAAFAAAAWzAAA      74374        5        1459         0
AAASKGAAFAAAAWzAAB      74374        5        1459         1
LEO1@LEO1> select object_name from dba_objects where object_id=74374;
OBJECT_NAME
--------------------------------------------------------------------------------
LEO1
上面两行记录的对象名即为Leo1,所属文件号是5(同一个文件),所属块号是1459(同一个块),所属行号0(第一行)1(第二行)以此类推。
小结:如果我们想要了解数据行的物理结构,那么可以通过DBMS_ROWID包来得到数据行的相关信息。

3.示例说明consistent read,current read,logical read,physical read的概念及关系
Logical read:所谓逻辑读,就是从内存中读取数据块,包含current read consistent read
current read:属于Oracle版本读取方式的一种机制,就是说当进行DML操作时,我们需要获取数据块最新的状态,只对最新状态进行操作,操作期间锁定数据行。
consistent read:当进行select查询时,我们需要获取查询那一刻数据块状态,不管查询了多长时间,我们只要查询那一瞬间的结果,如果查询期间数据块被修改,那么我们就去undo segment读取旧映像来呈现。
公式:logical read=db block gets(current read) + consistent gets(consistent read)
Physical read:所谓物理读,就是从磁盘中读取数据块
如果想了解更多的current read consistent read的信息请参考如下链接
《Oracle undo我们需要掌握什么》第五小题“示例分别说明什么是consistent readcurrent read?
http://space.itpub.net/26686207/viewspace-757488
LEO1@LEO1> drop table leo2 purge;                        清空环境
Table dropped.
LEO1@LEO1> create table leo2 as select * from dba_objects;     创建leo2
Table created.
LEO1@LEO1> set autotrace traceonly
LEO1@LEO1> select count(*) from leo2;                     查看一下SQL语句统计信息
Statistics
----------------------------------------------------------
         28  recursive calls
          0  db block gets
      1100  consistent gets      逻辑读中一致性读,发生了1100次(从内存中读取数据块)
       1025  physical reads      物理读发生了1025次(从磁盘中读取数据块)
          0  redo size
        528  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
逻辑读与物理读关系:逻辑读触发物理读的发生,因为oracle默认数据块在内存中,如果发现块不在内存里,就会触发物理读从磁盘上读取数据块到内存,在进行下面的逻辑读。
有物理读必有逻辑读,有逻辑读不一定有物理读,看看下面的样子
LEO1@LEO1> select count(*) from leo2;
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
       1030  consistent gets           只有逻辑读1030
          0  physical reads            没有物理读
          0  redo size
        528  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
原因:数据块现在已经全部缓存到内存中了,我们从内存中读取块即可,不用再从磁盘中读取块了,自然就没有物理读。

4.设计一个例子,演示PCTUSEDPCTFREE对数据操作的影响
PCTUSEDPCTFREE是数据块的存储属性,单位都是%
PCTFREE:表示什么时候不可以再往块中插入数据,但是更新数据和删除数据是可以的。例如我们设置为20%,当数据块空闲空间剩余20%时候,这个数据块就从空闲列表(free list)中移出,移出后我们就不能再往数据块里面插入数据了。对于数据块中已有数据的更新可以使用数据块中的保留空间,只有当数据块的占用空间比例(PCTUSED)低于40%时才能向其插入新数据。
PCTUSED:表示什么时候可以继续往块中插入数据,例如我们设置40%,只有当数据块占用容量低于40%时才允许再次插入新数据,此时数据块会插入空闲列表(free list),数据块就能够继续接受新记录,过程如此往复循环。
PCTUSEDPCTFREE二者没有任何关系,各做各的
场景:应用在OLTP系统上多,因为OLTP是一种多事务短时间片操作频繁的系统,设置数据块可以存放多少记录的容量有利于提高系统IO性能
Oracle 10g 11g PCTFREE默认值是10%,设置较高意味着数据块没有被利用多少就从freelist中移出,不利于数据块的充分使用(适合频繁更新的操作)。设置较低意味着更新时候会出现行迁移,从而也会影响Oracle的性能(适合频繁插入的操作)。
PCTUSED默认值是40%,设置较高意味着相对较满的数据块可有效循环使用空闲空间频繁插入,会导致IO资源的消耗较大,设置较低意味着当一个数据块快空的时候才被放入freelist,数据块一次可以插入很多数据,减少IO资源的消耗。
一般这两个值的总和不要大过90,否则会使Oracle将更多的时间花费在处理空间利用率上
实验
LEO1@LEO1> drop table leo4 purge;                        清空环境
Table dropped.
LEO1@LEO1> create table leo4 as select * from dba_objects;      创建一个新的leo4
Table created.
LEO1@LEO1> col table_name for a10
LEO1@LEO1> select table_name,tablespace_name,pct_free,pct_used from user_tables where table_name='LEO4';
TABLE_NAME    TABLESPACE_NAME     PCT_FREE    PCT_USED
---------- -----------------------------------------------------------------------------------
LEO4           LEO1                 10
LEO4表所在的表空间是ASSM段管理方式,在使用位图管理段空间的情况不可定义PCTUSED,只有使用MSSM段管理方式,在字典管理模式下才可调用free list,这2个参数可设置生效。
LEO1@LEO1> select segment_name,blocks,freelists from dba_segments where segment_name='LEO4';
SEGMENT_NAME     BLOCKS  FREELISTS
------------ ---------- ----------------------------------------
LEO4               1152
我们创建的leo4表,占用1152个数据块,freelistfreelistgroupASSM表空间中根本不存在,仅在MSSM表空间使用这个技术
详细出处参考:http://www.jb51.net/article/32017.htm
LEO1@LEO1> alter table leo4 pctfree 50;        修改pctfree=50
Table altered.
LEO1@LEO1> alter table leo4 pctused 40;        修改pctused=40
Table altered.
LEO1@LEO1> alter table leo4 move tablespace new_leo1;  把表leo4迁移到new_leo1表空间
Table altered.
new_leo1这个表空间是我之前已经创建好的一个ASSM表空间
语法:create tablespace new_leo1 datafile '/u01/app/oracle/oradata/LEO1/new_leo1.dbf' size 20m autoextend off;
LEO1@LEO1> select table_name,tablespace_name,pct_free,pct_used from user_tables where table_name='LEO4';
TABLE_NAME    TABLESPACE_NAME     PCT_FREE    PCT_USED
---------- -----------------------------------------------------------------------------------
LEO4           NEW_LEO1            50
从这里可以看到leo4表已经从leo1表空间迁移到new_leo1表空间了,pct_free也修改为50,而pct_usedASSM模型下依然不会生效的,freelist也不会生效。
LEO1@LEO1> select segment_name,blocks,freelists from dba_segments where segment_name='LEO4';
SEGMENT_NAME     BLOCKS  FREELISTS
------------ ---------- ----------------------------------------
LEO4               1920
从这里可以看到leo4表占用的块数从1152上升到1920,这就是因为我们修改了pctfree值得结果,原来默认值为10%的时候,我们可以有90%空间插入数据,现在修改成了50%,我们就只能有50%空间插入数据,存放数据的空间比从90%下降到50%,当数据总量不变的情况下,就只有增加数据块的个数来解决了。
下面我们演示PCTUSED参数的影响
MSSM:由你设置freelistsfreelistgroupspctusedpctfreeinitrans等参数来控制如何分配、使用段中的空间
ASSM:你只需控制一个参数pctfree,其他参数即使建了也将被忽略
LEO1@LEO1> create tablespace mssm_leo1 datafile '/u01/app/oracle/oradata/LEO1/mssm_leo1.dbf' size 50m autoextend off segment space management manual;
Tablespace created.
LEO1@LEO1> select tablespace_name,segment_space_management from user_tablespaces where tablespace_name in ('LEO1','NEW_LEO1','MSSM_LEO1');
TABLESPACE_NAME                SEGMEN
------------------------------ ---------------- ---------------- ------
LEO1                           AUTO
NEW_LEO1                      AUTO
MSSM_LEO1                     MANUAL
我们创建一个手动段空间管理MSSM的表空间,在上面创建个新表leo5
LEO1@LEO1> drop table leo5 purge;               清理环境
Table dropped.
LEO1@LEO1> create table leo5 tablespace mssm_leo1 as select * from dba_objects;
Table created.创建表并指定MSSM表空间存储
LEO1@LEO1> select table_name,tablespace_name,pct_free,pct_used,freelists,freelist_groups from user_tables where table_name='LEO5';
TABLE_NAME TABLESPACE_N    PCT_FREE   PCT_USED  FREELISTS FREELIST_GROUPS
--------------------------------------------------------------------------------------------------------------------------
LEO5        MSSM_LEO1     10         40         1        1
此时我们就可以使用上述参数来控制如何分配和使用段中空间了
LEO1@LEO1> select segment_name,blocks,freelists,freelist_groups from dba_segments where segment_name='LEO5';
SEGMENT_NAME     BLOCKS  FREELISTS FREELIST_GROUPS
------------ ---------- ---------- ------------------------- ---------- ---------------
LEO5               1152          1               1
LEO1@LEO1> alter table leo5 pctfree 20;
Table altered.
LEO1@LEO1> alter table leo5 pctused 50;
Table altered.
LEO1@LEO1> select segment_name,blocks,freelists,freelist_groups from dba_segments where segment_name='LEO5';
SEGMENT_NAME     BLOCKS  FREELISTS FREELIST_GROUPS
------------ ---------- ---------- ------------------------- ---------- ---------------
LEO5               1152          1               1
pctused的变化并不会影响第一次加载的数据,因为原始数据块一开始都是空的,不管如何设置pctused数据都可以顺利加载进来,只对后面的加载会有影响。
LEO1@LEO1> select table_name,tablespace_name,pct_free,pct_used,freelists,freelist_groups from user_tables where table_name='LEO5';
TABLE_NAME TABLESPACE_N    PCT_FREE   PCT_USED  FREELISTS FREELIST_GROUPS
--------------------------------------------------------------------------------------------------------------------------
LEO5        MSSM_LEO1     20         50         1        1
我们修改一下pctfreepctused,可以看到在MSSM段空间管理模式下都是生效的。
LEO1@LEO1> drop table leo6 purge;     清理环境
Table dropped.
LEO1@LEO1> drop table leo7 purge;
Table dropped.
LEO1@LEO1> create table leo6 tablespace mssm_leo1 as select * from dba_objects;创建leo6
Table created.
LEO1@LEO1> create table leo7 tablespace mssm_leo1 as select * from dba_objects;创建leo7
Table created.
LEO1@LEO1> execute dbms_stats.gather_table_stats(ownname=>'LEO1',tabname=>'LEO6');
PL/SQL procedure successfully completed.
LEO1@LEO1> execute dbms_stats.gather_table_stats(ownname=>'LEO1',tabname=>'LEO7');
PL/SQL procedure successfully completed.
进行统计分析收集表存储信息
LEO1@LEO1> select table_name,tablespace_name,pct_free,pct_used,blocks,freelists,freelist_groups from user_tables where table_name='LEO6';
TABLE_NAME  TABLESPACE_N   PCT_FREE   PCT_USED     BLOCKS  FREELISTS FREELIST_GROUPS
---------------------------------------------------------------------------------------------------------------------------------------------
LEO6         MSSM_LEO1     10         40           1024     1       1
LEO1@LEO1> select table_name,tablespace_name,pct_free,pct_used,blocks,freelists,freelist_groups from user_tables where table_name='LEO7';
TABLE_NAME  TABLESPACE_N   PCT_FREE   PCT_USED     BLOCKS  FREELISTS FREELIST_GROUPS
---------------------------------------------------------------------------------------------------------------------------------------------
LEO7         MSSM_LEO1     10         40           1024     1       1
我们在初始化表时,PCT_FREE=10  PCT_USED=40   BLOCKS=1024,下面我们只修改PCT_USED
LEO1@LEO1> alter table leo6 pctused 30;
Table altered.
LEO1@LEO1> alter table leo7 pctused 60;
Table altered.
LEO1@LEO1> select table_name,tablespace_name,pct_free,pct_used,blocks,freelists,freelist_groups from user_tables where table_name in ('LEO6','LEO7');
TABLE_NAME  TABLESPACE_N   PCT_FREE   PCT_USED     BLOCKS  FREELISTS FREELIST_GROUPS
---------------------------------------------------------------------------------------------------------------------------------------------
LEO6         MSSM_LEO1     10         30           1024     1       1
LEO7         MSSM_LEO1     10         60           1024     1       1
已经修改完成,但没有影响数据块分配数量,这是正常的,既然PCT_USED是表示何时该插入的阀值,那么我们可以delete where where object_type in ('TABLE','INDEX','VIEW','SEQUENCE');一些记录,降低到阀值的允许范围内,在插入一些记录,设置较高意味着相对较满的数据块可有效循环使用空闲空间频繁插入,此时占用的数据块应该较少,反之较多。
LEO1@LEO1> delete from leo6 where object_type in ('TABLE','INDEX','VIEW','SEQUENCE');
11870 rows deleted.
LEO1@LEO1> delete from leo7 where object_type in ('TABLE','INDEX','VIEW','SEQUENCE');
11870 rows deleted.                              删除11870
LEO1@LEO1> insert into leo6 select * from leo5;
71969 rows created.
LEO1@LEO1> insert into leo7 select * from leo5;
71969 rows created.                              插入71969
LEO1@LEO1> execute dbms_stats.gather_table_stats(ownname=>'LEO1',tabname=>'LEO6');
PL/SQL procedure successfully completed.
LEO1@LEO1> execute dbms_stats.gather_table_stats(ownname=>'LEO1',tabname=>'LEO7');
PL/SQL procedure successfully completed.
LEO1@LEO1> select table_name,tablespace_name,pct_free,pct_used,blocks,freelists,freelist_groups from user_tables where table_name in ('LEO6','LEO7');
TABLE_NAME  TABLESPACE_N   PCT_FREE   PCT_USED     BLOCKS  FREELISTS FREELIST_GROUPS
---------------------------------------------------------------------------------------------------------------------------------------------
LEO6         MSSM_LEO1     10         30           1959    1        1
LEO7         MSSM_LEO1     10         60           1901    1        1
小结:leo7占用数据块比leo6少,是因为当后续加载数据时,Oracle会根据PCT_USED参数动态调节数据块何时可以继续插入数据,当删除后阀值降到了60%以下就可以往leo7表中的块插入数据,当删除后阀值降到了30%以下才可以往leo6表中的块插入数据,由此看来,leo7中的块利用率较高,但IO资源开销较大,在平时使用时可以根据业务特性结合测试结果灵活设定。

5.设计一个例子,演示数据块整理(合并)的效果
场合:
1)当insert update操作的行在一个数据块中有足够的空闲空间,但这个空闲空间是碎片状态,又无法满足一行数据的使用,此时Oracle会自动进行空闲空间合并。
2)空闲空间合并会消耗大量系统资源,只在必要情况下进行手工合并。
3)当我们批量delete删除记录时并不会回收HWM高水位线,oracle在扫描表时依然从第一个块扫描到最后的HWM,扫描时间过长性能下降,在插入新记录时,也是从HWM之后开始插入,之前标识的删除记录所占用的磁盘空间并没有释放,这在磁盘空间较紧张的情况下是不能接受的。我们必须合并那些碎片空间,收集起来循环利用,提高磁盘使用率和检索效率。
4)合并空闲碎片空间的方法有很多,例如 move  rebuild  shrink表等都可实现
shrink表实现合并碎片空间请参考http://f.dataguru.cn/thread-93740-1-1.html
下面我采用move表方式实现碎片的回收,先介绍一下这种方式的特点
1.不支持在线读/
2.表在移动的过程中是锁定状态不能操作  
3.表在移动后表上索引会失效,必须rebuild重建
4.可以整合碎片
LEO1@LEO1> drop table leo3 purge;                              清空环境
Table dropped.
LEO1@LEO1> create table leo3 as select * from dba_objects;           创建leo3
Table created.
LEO1@LEO1> create index idx_leo3 on leo3(object_id);               创建索引
Index created.
LEO1@LEO1> execute dbms_stats.gather_table_stats(ownname=>'LEO1',tabname=>'LEO3',cascade=>true);
PL/SQL procedure successfully completed.                          做表和索引分析
LEO1@LEO1> select table_name,tablespace_name from user_tables where table_name = 'LEO3';
TABLE_NAME                    TABLESPACE_NAME
------------------------------ -----------------------------------------------
LEO3                           LEO1
我们创建的leo3表所属表空间为leo1
LEO1@LEO1> select index_name,table_name,tablespace_name,status from user_indexes where index_name='IDX_LEO3';
INDEX_NAME      TABLE_NAME      TABLESPACE_NAME      STATUS
---------------------------------------------------------------------------------------------------------------
IDX_LEO3          LEO3            LEO1                  VALID
我们创建的idx_leo3索引所属leo1表空间并且状态是有效的
LEO1@LEO1> select segment_name,blocks from dba_segments where segment_name='LEO3';
SEGMENT_NAME    BLOCKS
----------------------------------------------
LEO3              1152
我们leo3表目前占用1152个块
LEO1@LEO1> select count(*) from leo3;                 表中有71968条记录
  COUNT(*)
------------------
     71968
LEO1@LEO1> delete from leo3 where rownum<40000;     删除4w
39999 rows deleted.
LEO1@LEO1> commit;                                提交
Commit complete.
LEO1@LEO1> select count(*) from leo3;                  还剩31969
  COUNT(*)
------------------
     31969
LEO1@LEO1> select segment_name,blocks from dba_segments where segment_name='LEO3';
SEGMENT_NAME    BLOCKS
----------------------------------------------
LEO3              1152
我们现在已经删除了表中一半数据,但是占用的数据块毅然决然是1152个块,HWM没有回收,删除记录的数据块没有释放,这时候就需要合并释放空闲空间了。
LEO1@LEO1> select name from v$datafile where rownum=1;     看一下创建表空间路径
NAME
--------------------------------------------------------------------------------
/u01/app/oracle/oradata/LEO1/system01.dbf
LEO1@LEO1> create tablespace new_leo1 datafile '/u01/app/oracle/oradata/LEO1/new_leo1.dbf' size 20m autoextend off;
Tablespace created.
我们创建一个新的表空间new_leo1大小20M非自动扩展
LEO1@LEO1> alter table leo3 move tablespace new_leo1;
Table altered.
现在我们把leo3表从leo1表空间movenew_leo3表空间,表在移动的过程中是锁定状态不能操作
LEO1@LEO1> select table_name,tablespace_name from user_tables where table_name = 'LEO3';
TABLE_NAME                     TABLESPACE_NAME
--------------------------------------------------------------------------------
LEO3                            NEW_LEO1
此时已经把表迁移到了NEW_LEO1表空间
LEO1@LEO1> select index_name,table_name,tablespace_name,status from user_indexes where index_name='IDX_LEO3';
INDEX_NAME      TABLE_NAME      TABLESPACE_NAME      STATUS
---------------------------------------------------------------------------------------------------------------
IDX_LEO3          LEO3            LEO1                  UNUSABLE
表在move后表上的索引会失效,必须rebuild
LEO1@LEO1> select segment_name,blocks from dba_segments where segment_name='LEO3';
SEGMENT_NAME    BLOCKS
----------------------------------------------
LEO3              512
见证奇迹的时刻,leo3表占用块数为512个,leo3表经过移动后释放了一半空间,在数据块搬家过程中我们从一个碎片奇多的表空间搬到了一个新表空间,数据重新排列杜绝碎片产生。
LEO1@LEO1> alter index idx_leo3 rebuild online;      重建索引
Index altered.
online作用:加online可以在重建索引的过程中对表进行DML操作,不加online必须等待索引重建完成后才能对表进行DML操作(在重建过程中锁定表)
LEO1@LEO1> select index_name,table_name,tablespace_name,status from user_indexes where index_name='IDX_LEO3';
INDEX_NAME      TABLE_NAME      TABLESPACE_NAME      STATUS
---------------------------------------------------------------------------------------------------------------
IDX_LEO3          LEO3            LEO1                  VALID
完美大功告成

extents,blocks,consistent_read,current_read,logical_read,physical_read,pctfree,pctused

Leonarding
2013.4.7
天津&spring
分享技术~成就梦想

Blogwww.leonarding.com
原创粉丝点击