【oracle11g,17】存储结构: 段的类型,数据块(行连接、行迁移,块头),段的管理方式,高水位线

一.段的类型:
1.什么是段:段是存储单元。
1.段的类型有: 
分区表
簇表
索引
索引组织表(IOT表)
分区索引
临时段
undo段
lob段(blob ,clob)
内嵌表(record类型,table类型)
启动段 :打开数据库时要装入的数据字典系统信息,故在系统表空间内。

注意:smon 回收不用的临时段和undo段。

2.表:
 表是存储数据的逻辑单位。
  表的功能: 存储、管理数据的基本单元,
  表的类型: 
      普通表:堆表,

例:查询表的行的平均长度
AVG_ROW_LEN 平均长度
avg_space 平均空间
SQL> select table_name,tablespace_name,blocks,pct_free,pct_used,avg_space,AVG_ROW_LEN from dba_tables where table_name like ‘EMP%‘;

TABLE_NA TABLESPACE_N     BLOCKS   PCT_FREE   PCT_USED  AVG_SPACE AVG_ROW_LEN
-------- ------------ ---------- ---------- ---------- ---------- -----------
EMP1     SYSTEM               44         10         40          0          38
EMP      USERS                 1         10         40          0          38
EMPLX    LXTBS2               10         10         40       1322          38

例:查询表默认的pctfree 和pctused 以及修改
SQL> select table_name,tablespace_name,blocks,pct_free,pct_used from dba_tables where table_name like ‘EMP%‘;

TABLE_NA TABLESPACE_N     BLOCKS   PCT_FREE   PCT_USED
-------- ------------ ---------- ---------- ----------
EMP1     SYSTEM               44         10         40
EMPLX    LXTBS2               10         10         40
EMP      USERS                 1         10         40

SQL> alter table emplx pctfree 12;

Table altered.

SQL> alter table emplx pctused 42;

Table altered.


3.分区表:
比如一个表尺寸大于2g,oracle建议分区,一个分区内的数据量一般不超过50w左右性能最好,最多不要超过100万。
range分区方式,按照指定范围分区,比如按时间分区或值大小分区。
list分区方式,是一种列举方式进行分区
哈数分区方式, 根据hash算法分区,有oracle管理。

①.分区表的使用详见:【dba,32】分区表:

②.案例:创建分区索引


#创建分区表
SQL> CREATE TABLE sales_history
  2              (id number(8),name varchar2(30),sales_date date)
  3     PARTITION BY RANGE (sales_date)
  4    (PARTITION p1 VALUES LESS THAN ( TO_DATE(‘01-JAN-1999‘,‘DD-MON-YYYY‘)) tablespace users,
  5     PARTITION p2 VALUES LESS THAN ( TO_DATE(‘01-JAN-2000‘,‘DD-MON-YYYY‘)) tablespace users,
  6     PARTITION p3 VALUES LESS THAN ( TO_DATE(‘01-JAN-2001‘,‘DD-MON-YYYY‘)) tablespace users,
  7     PARTITION p4 VALUES LESS THAN ( TO_DATE(‘01-JAN-2002‘,‘DD-MON-YYYY‘)) tablespace users,
  8     PARTITION p5 VALUES LESS THAN (MAXVALUE) tablespace users
  9    );

Table created.
#插入数据
SQL> insert into sales_history values(1,‘PC1‘,to_date(‘17-FEB-2000‘,‘DD-MON-YYYY‘));
SQL> insert into sales_history values(2,‘PC2‘,to_date(‘17-FEB-2001‘,‘DD-MON-YYYY‘))
SQL> insert into sales_history values(3,‘PC3‘,to_date(‘17-FEB-2002‘,‘DD-MON-YYYY‘));
SQL> insert into sales_history values(4,‘PC4‘,to_date(‘17-FEB-1999‘,‘DD-MON-YYYY‘));

SQL> insert into sales_history values(5,‘PC5‘,to_date(‘15-FEB-2000‘,‘DD-MON-YYYY‘));
SQL> insert into sales_history values(6,‘PC6‘,to_date(‘12-FEB-2001‘,‘DD-MON-YYYY‘));
SQL> insert into sales_history values(7,‘PC7‘,to_date(‘11-FEB-1998‘,‘DD-MON-YYYY‘));
SQL> insert into sales_history values(8,‘PC8‘,to_date(‘13-FEB-2002‘,‘DD-MON-YYYY‘));

SQL> insert into sales_history values(8,‘PC8‘,to_date(‘13-FEB-2013‘,‘DD-MON-YYYY‘));

#查询数据
SQL> select * from sales_history;

        ID NAME       SALES_DAT
---------- ---------- ---------
         7 PC7        11-FEB-98
         4 PC4        17-FEB-99
         1 PC1        17-FEB-00
         5 PC5        15-FEB-00
         2 PC2        17-FEB-01
         6 PC6        12-FEB-01
         3 PC3        17-FEB-02
         8 PC8        13-FEB-02
         8 PC8        13-FEB-13

9 rows selected.
#查询分区表数据
SQL> select * from sales_history partition(p1);

        ID NAME       SALES_DAT
---------- ---------- ---------
         7 PC7        11-FEB-98

SQL> select * from sales_history partition(p2);

        ID NAME       SALES_DAT
---------- ---------- ---------
         4 PC4        17-FEB-99

SQL> select * from sales_history partition(p3);

        ID NAME       SALES_DAT
---------- ---------- ---------
         1 PC1        17-FEB-00
         5 PC5        15-FEB-00

SQL> select * from sales_history partition(p4);

        ID NAME       SALES_DAT
---------- ---------- ---------
         2 PC2        17-FEB-01
         6 PC6        12-FEB-01

SQL> select * from sales_history partition(p5);

        ID NAME       SALES_DAT
---------- ---------- ---------
         3 PC3        17-FEB-02
         8 PC8        13-FEB-02
         8 PC8        13-FEB-13

#创建唯一索引 ,因为数据中id有重复,所以报错。
SQL> CREATE unique INDEX i_sales_id ON sales_history(id) GLOBAL
  2       PARTITION BY HASH (id)
  3       (PARTITION pi1  TABLESPACE users,
  4        PARTITION pi2  TABLESPACE users,
  5        PARTITION pi3  TABLESPACE users,
  6        PARTITION pi4  TABLESPACE users) parallel 4;

CREATE unique INDEX i_sales_id ON sales_history(id) GLOBAL
*
ERROR at line 1:
ORA-12801: error signaled in parallel query server P001
ORA-01452: cannot CREATE UNIQUE INDEX; duplicate keys found

#根据rowid查询和删除重复数据:
SQL> select a.* from sales_history a 
  2  where a.rowid in (
  3  select min(b.rowid) from sales_history b
  4  where b.id=a.id);

        ID NAME       SALES_DAT
---------- ---------- ---------
         7 PC7        11-FEB-98
         4 PC4        17-FEB-99
         1 PC1        17-FEB-00
         5 PC5        15-FEB-00
         2 PC2        17-FEB-01
         6 PC6        12-FEB-01
         3 PC3        17-FEB-02
         8 PC8        13-FEB-02

8 rows selected.
#查询出多余的数据
SQL> select a.* from sales_history a
  2  where a.rowid not in (
  3  select min(b.rowid) from sales_history b
  4  where b.id=a.id);

        ID NAME       SALES_DAT
---------- ---------- ---------
         8 PC8        13-FEB-13

SQL> select a.*,rowid from sales_history a;

        ID NAME       SALES_DAT ROWID
---------- ---------- --------- ------------------
         7 PC7        11-FEB-98 AAACffAAEAAAAA9AAA
         4 PC4        17-FEB-99 AAACfgAAEAAAABFAAA
         1 PC1        17-FEB-00 AAACfhAAEAAAABNAAA
         5 PC5        15-FEB-00 AAACfhAAEAAAABNAAB
         2 PC2        17-FEB-01 AAACfiAAEAAAABVAAA
         6 PC6        12-FEB-01 AAACfiAAEAAAABVAAB
         3 PC3        17-FEB-02 AAACfjAAEAAAABdAAA
         8 PC8        13-FEB-02 AAACfjAAEAAAABdAAB
         8 PC8        13-FEB-13 AAACfjAAEAAAABdAAC

9 rows selected.
#删除重复的数据
SQL> delete from sales_history a          
  2  where a.rowid not in (
  3  select min(b.rowid) from sales_history b
  4  where b.id=a.id);
SQL> CREATE unique INDEX i_sales_id ON sales_history(id) GLOBAL
  2       PARTITION BY HASH (id)
  3       (PARTITION pi1  TABLESPACE users,
  4        PARTITION pi2  TABLESPACE users,
  5        PARTITION pi3  TABLESPACE users,
  6        PARTITION pi4  TABLESPACE users) parallel 4;

Index created.

注意:parallel 在生成库上慎重使用,可能会把cpu的资源消耗干。
注意:对某个字段已做了分区了,是不允许再建立索引分区的。这一点要非常注意。

#创建本地索引
SQL> CREATE INDEX i_sales_date on sales_history(sales_date) local;

Index created.
#创建一个不分区的索引
SQL>  CREATE INDEX i_sales_name on sales_history(name);

#查询索引,partitioned 为YES表示分区索引。
SQL> select index_name,index_type,table_name,tablespace_name,partitioned from dba_indexes where table_name=‘SALES_HISTORY‘;

INDEX_NAME           INDEX_TYPE TABLE_NAME           TABLESPACE PAR
-------------------- ---------- -------------------- ---------- ---
I_SALES_ID           NORMAL     SALES_HISTORY                   YES
I_SALES_DATE         NORMAL     SALES_HISTORY                   YES
I_SALES_NAME         NORMAL     SALES_HISTORY        SYSTEM     NO

#truncate 分区。
SQL> alter table sales_history truncate partition p2 update indexes;
Table truncated.

#重建分区索引
SQL>  alter index i_sales_date rebuild partition p3;
Index altered.

#添加分区
SQL> alter table sales_history add partition p6 values less than (to_date(‘2019-01-01‘,‘yyyy-mm-dd‘))  ;

3.2. PARTITION BY  REFERENCE:
http://docs.oracle.com/cd/E11882_01/server.112/e25523/part_admin001.htm#i1006455 
4.簇表:
主要用于表和表之间的连接查询
访问不同的表时要访问不同的段,磁盘会访问不同的磁道,如果两个表能存放到一个段,就能提高访问速度。
一个簇是由共享相同数据块的一组表组成,因为这些表共享公共的列并且经常一起被使用,所以将这些表组合在一起。
簇表优点: 减少了磁盘i/o并改善了访问簇表的连接所化的时间。
         簇键是列或列的组,他们是簇表所共用的创建簇时指定簇键的列,


例:创建簇表
#关联查询
SQL> select e.empno,e.ename,e.sal,d.deptno,d.dname from scott.emp e,scott.dept d where e.deptno=d.deptno;

14 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 615168685

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    14 |   952 |     7  (15)| 00:00:01 |
|*  1 |  HASH JOIN         |      |    14 |   952 |     7  (15)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| DEPT |     4 |    88 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| EMP  |    14 |   644 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------


#创建簇键
SQL> CREATE CLUSTER emp_dept (deptno NUMBER(3))
  2     SIZE 600
  3     TABLESPACE users;

Cluster created.
#创建簇表 先创建dept,然后再创建emp表。否则报错。
SQL> create table dept(
  2   DEPTNO                        NUMBER(3) primary key,
  3   DNAME                         VARCHAR2(14),
  4   LOC                           VARCHAR2(13)
  5  ) CLUSTER emp_dept (deptno);

Table created.
#创建簇表
SQL> create table emp(
  2   EMPNO                         NUMBER(4) primary key,
  3   ENAME                         VARCHAR2(10),
  4   JOB                           VARCHAR2(9),
  5   MGR                           NUMBER(4),
  6   HIREDATE                      DATE,
  7   SAL                           NUMBER(7,2),
  8   COMM                          NUMBER(7,2),
  9   DEPTNO                        NUMBER(3) references dept(deptno)
 10  ) CLUSTER emp_dept (deptno);

Table created.
#创建簇索引
SQL> CREATE INDEX emp_dept_index
  2     ON CLUSTER emp_dept
  3     TABLESPACE users;

Index created.
#插入数据
SQL> insert into dept select * from scott.dept;

4 rows created.

SQL> insert into emp select * from scott.emp;

14 rows created.

SQL> commit;

Commit complete.
#查询两个表的rowid,rowid的前15位相同说明在同一个数据块中。
SQL> select e.rowid,d.rowid from emp e,dept d where e.deptno=d.deptno;

ROWID              ROWID
------------------ ------------------
AAACgFAAEAAAACVAAA AAACgFAAEAAAACVAAB
AAACgFAAEAAAACVAAB AAACgFAAEAAAACVAAC
AAACgFAAEAAAACVAAC AAACgFAAEAAAACVAAC
AAACgFAAEAAAACVAAD AAACgFAAEAAAACVAAB
AAACgFAAEAAAACVAAE AAACgFAAEAAAACVAAC
AAACgFAAEAAAACVAAF AAACgFAAEAAAACVAAC
AAACgFAAEAAAACVAAG AAACgFAAEAAAACVAAA
AAACgFAAEAAAACVAAH AAACgFAAEAAAACVAAB
AAACgFAAEAAAACVAAI AAACgFAAEAAAACVAAA
AAACgFAAEAAAACVAAJ AAACgFAAEAAAACVAAC
AAACgFAAEAAAACVAAK AAACgFAAEAAAACVAAB

ROWID              ROWID
------------------ ------------------
AAACgFAAEAAAACVAAL AAACgFAAEAAAACVAAC
AAACgFAAEAAAACVAAM AAACgFAAEAAAACVAAB
AAACgFAAEAAAACVAAN AAACgFAAEAAAACVAAA

14 rows selected.

#扫描方式发生变化
SQL> select e.empno,e.ename,e.sal,d.deptno,d.dname from emp e,dept d where e.deptno=d.deptno;

14 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 805422011

----------------------------------------------------------------------------------------
| Id  | Operation             | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |                |    14 |   952 |     6   (0)| 00:00:01 |
|   1 |  NESTED LOOPS         |                |    14 |   952 |     6   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL   | DEPT           |     4 |    88 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS CLUSTER| EMP            |     4 |   184 |     1   (0)| 00:00:01 |
|*  4 |    INDEX UNIQUE SCAN  | EMP_DEPT_INDEX |     1 |       |     0   (0)| 00:00:01 |
----------------------------------------------------------------------------------------



5.索引:
加快查询速度,索引第一次IO先访问树,到叶节点找到rowid,再通过rowid访问响应的记录。

6.索引组织表(IOT表):
可以将数据存放在索引的叶节点,不用再访问不同的段,iot表不能换查询条件,查询条件必须建成主键约束,如果换查询条件效率会很低。
  iot表存储时根据主键排序进行存储,所以插入数据时,按顺序插入数据。
  如果索引组织表中的数据放不下会把一些数据放到溢出表空间
优点:只要io一次就能找到真实数据。
注意:生产中慎重使用

例:将多对多的关系表创建索引组织表
SQL> create table students(stud_id number,fname varchar2(30),lname varchar2(30),constraint pk_student primary key(stud_id));
Table created.

SQL> create table classes(class_id number,cname varchar2(30),constraint pk_class primary key(class_id));
Table created.

#创建索引组织表,

SQL> create table attendees(stud_id number,class_id number,
  2  constraint pk_stud_class primary key(stud_id,class_id),
  3  constraint fk_stud foreign key(stud_id) references students(stud_id),
  4  constraint fk_class foreign key(class_id) references classes(class_id)
  5  ) organization index;



7.分区索引类型:
  ①.表是分区表,索引不分区:
  ②.分区表的全局分区索引: 
    缺点:在truncate表时,这种索引会失效。
    优点:global所以在全局是有序的,所以效率高。
    
  ③.分区表的local分区索引:
    语法:create index inx_tab_partition_col table_partition(col1) local;
   缺点:
     分区上的位图索引只能为local索引,不能为global全局索引。
     local分区索引在每个分区上有序,但在全局是无序的,索引查询效率没有全局分区索引高。
   优点:在olap系统中应用广泛,在truncate表时,这种索引不会失效。易于管理。


二.数据块:(pctfree和pctused,行连接、行迁移、数据块)

1.数据块分为三部分:block header(块头),free space(空闲空间), row data(数据行)。

2.pctfree 和pctused
pctfree就是插入数据到数据块中,达到pctfree时就不在插入数据,pctfree就是为update预留的空间。
pctused就是数据块中存放的数据在pctused之下表示数据块为空块,在段空间手工管理的情况下,就会把这些数据块放到链表freelist队列中,用于再次插入数据。

pctfree 太小在update操作时会导致行迁移,
pctused 太大在insert操作时会导致行连接。
3.行迁移(row migrate)和行连接(row chain)
行迁移:由于update操作导致原本在该块中的记录放不下了,就保留一个该行记录的地址,然后将该行记录迁移到其他块中,但是rowid不变。
行连接: 就是一行数据insert到一个块时,根本容不下这行数据,该条记录只能把数据分别放到若干个数据块中,使用row chain连接起来。long或long row数据类型的时候容易产生行连接。


4.数据块头:
块头包括表目录,行目录。
表目录:
  这部分信息包含了在这个块中该表或该索引的相关信息。
行目录:
  包含数据块中的实际行的信息(包括行数据区域中每行的地址)
事务槽 (ITL:interested transaction list):
  ①. 表初始事务槽是1,索引默认为2,事务表会根据需要动态扩展,用来记录该数据块所有发生的事务。如果事务已经提交,那么这个itl的位置就可以被反复使用了。
  ②.多个事务同时修改同一数据块时,就会有多个事务槽,事务槽被占用完了(数据块可用的空间被用完) 当再有事务要操作数据块时,需要等待其他事务提交后,才能进行操作,此时就是事务槽的争用
  查看事务槽:
  SQL> select table_name ,tablespace_name,blocks,ini_trans,max_trans from dba_tables where table_name like ‘EMP%‘;
TABLE_NAME                     TABLESPACE_NAME     BLOCKS  INI_TRANS  MAX_TRANS
------------------------------ --------------- ---------- ---------- ----------
EMP1                           SYSTEM                  44          1        255
EMP                            USERS                    1          1        255

  SQL> select index_name,index_type,table_name,tablespace_name,ini_trans,max_trans  from dba_indexes where owner=‘SCOTT‘;
INDEX_NAME INDEX_TYPE TABLE_NAME      TABLESPACE_NAME  INI_TRANS  MAX_TRANS
---------- ---------- --------------- --------------- ---------- ----------
PK_EMP     NORMAL     EMP             USERS                    2        255
PK_DEPT    NORMAL     DEPT            USERS                    2        255

三.段的管理方式(两种)
自动段空间管理(ASSM)(数据库默认的管理形式)和手动段空间管理

1.自动段空间管理(ASSM)auto segment space manage
不访问freelist而是访问自己段头的位图,极大地减少了竞争。
连接列表freelist被位图所取代,它是一个二进制的数组,能够快速有效的管理存储扩展和剩余区块(free block),因此能够改善分段存储本质,assm 表空间上创建的段还有另外一个称呼叫bitmap managed segments (BMB段)。


assm优点:减轻缓冲区忙等待(buffer busy waits)的负担,有assm之后,oracle提高了DML并发操作的性能。因为位图的不同部分可以被同时使用,这样就消除了寻找剩余空间的串行化。根据oracle的测试结果,使用位图会消除所用分段头部的争夺,还能获得超快的并发插入操作。消除并发插入的热快问题和buffer busy wait。

assm的局限性: 无法控制tablespace内部的独立表和索引的存储行为
             大型对象不能使用assm,而且必须为包含lob数据类型的表创建分离的tablespace。
             不能使用assm创建临时表空间,这是由于排序时临时分段的短暂特性所决定的。
             只用本地管理的tablespace才能使用位图分段管理。
             使用超高容量的dml的时候可能会出现性能上的问题

注意:不要与内存分配自动管理(asmm)混淆。

2.手动段空间管理(MSSM)
系统会在段头建立一个fresslist链表,我们会把有空闲空间的块,放到列表中。当块中的数据量少于pctused会插入freelist。 然而链表freelist是串行化操作。
在没有多个freelist的时候,当数据缓冲内的数据块由于被另一个dml事务处理锁定而无法使用的时候,缓冲区忙等待就会发生,当你需要将多个任务插入到同一表格里的时候,这些任务就被强制等待,而同时oracle会在同时分派剩余的区块,一次一个(buffer busy wait)。

很多用户都访问freelist 形成热块。

3.两种段空间的管理比较:
 相同点: 主要是管理已经分配给段的数据块
 不同点:  手工段空间管理方式:pctfree和pctused 都有效。
         自动段空间管理方式:只使用pctfree来决定是不是空块,pctused 被位图的四个状态位所取代(如:>75%,50%~75%,50%~25%,<25%)。
         assm无法控制tablespace内部的独立表和索引的存储行为。
         mssm可以控制tablespace内部的独立表和索引的存储行为。



4.查看段的管理方式
SQL> select tablespace_name ,contents,status,extent_management,segment_space_management from dba_tablespaces;

TABLESPACE_NAME                CONTENTS  STATUS    EXTENT_MAN SEGMEN
------------------------------ --------- --------- ---------- ------
SYSTEM                         PERMANENT ONLINE    LOCAL      MANUAL
SYSAUX                         PERMANENT ONLINE    LOCAL      AUTO
UNDOTBS                        UNDO      ONLINE    LOCAL      MANUAL
USERS                          PERMANENT ONLINE    LOCAL      MANUAL
TEMPTS2                        TEMPORARY ONLINE    LOCAL      MANUAL
LXTBS1                         PERMANENT ONLINE    LOCAL      AUTO
LXTBS2                         PERMANENT ONLINE    LOCAL      AUTO
LXTBS3                         PERMANENT ONLINE    LOCAL      AUTO
TEMPTS                         TEMPORARY ONLINE    LOCAL      MANUAL


四.区的管理方式和段的管理方式的区别:

区的管理方式: 区来自表空间,这些数据块还没有被分配出去。
段的管理方式:主要是管理已经分配给段的数据块,


五.创建assm和mssm管理的表空间:
1.创建ASSM段管理的表空间 (数据库段空间管理默认方式为ASSM)
SQL> create tablespace lxtbs1 datafile ‘/u01/app/oracle/oradata/prod/disk3/lxtbs01.dbf‘ size 50m segment space management auto;
或者
create tablespace lxtbs1 datafile ‘/u01/app/oracle/oradata/prod/disk3/lxtbs01.dbf‘ size 50m;
2.创建MSSM手工管理的表空间
SQL> create tablespace lxtbs2 datafile ‘/u01/app/oracle/oradata/prod/disk3/lxtbs01.dbf‘ size 50m segment space management manual;


六.在mssm段管理方式的表空间创建表并设计表空间分配 :
注意:只能在mssm段管理的方式的表空间上才能对表的空间分配进行设计。

#创建表
SQL> create table emplx tablespace lxtbs2 storage(initial 32k next 64k pctincrease 50) as select * from scott.emp;
#插入数据
SQL>insert into emplx  select * from emplx;
#查询段的空间分配情况
SQL> select segment_name,segment_type,tablespace_name,bytes/1024 k,extents,blocks,initial_extent/1024 init,next_extent/1024 next,pct_increase from dba_segments where segment_name like ‘EMP%‘;
SEGMENT_NA SEGMENT_TYPE TABLESPACE_NAME          K    EXTENTS     BLOCKS       INIT       NEXT  PCT_INCREASE---------- ------------ --------------- ---------- ---------- ---------- ---------- ----------  ------------

EMP        TABLE        USERS                   64          1          8         64       1024

EMPLX      TABLE        LXTBS2                 192          3         24         32         64

EMP1       TABLE        SYSTEM                 384          6         48         64       1024



七.高水位线:
1.高水位线介绍:
(段使用区的最后一个块的位置叫高水位线), 高水位线是oracle对表进行全表扫描的最后的位置。当数据删除,高水位线并不会下降。



2.分析表: 实验比较truncate与delete的区别
使用:analyze table emplx compute statistics;命令分析表(计算表,一般用于小表)。
     SQL> analyze table scott.emp estimate statistics;(对表进行估算,一般用于大表)。
  SQL> exec DBMS_STATS.GATHER_TABLE_STATS(‘SCOTT‘,‘EMP‘); (plsql分析表)。

#查看执行计划
SQL> select * from emplx;

Execution Plan
----------------------------------------------------------
Plan hash value: 155704778

---------------------------------------------------------------------------
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |       |  3584 |   112K|     8   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| EMPLX |  3584 |   112K|     8   (0)| 00:00:01 |
---------------------------------------------------------------------------



SQL> select table_name,tablespace_name,blocks, empty_blocks from dba_tables where table_name=‘EMPLX‘;

TABLE_NAME      TABLESPACE_NAME     BLOCKS EMPTY_BLOCKS
--------------- --------------- ---------- ------------
EMPLX           LXTBS2

#分析表
SQL> analyze table emplx compute statistics;

Table analyzed.

SQL> select table_name,tablespace_name,blocks, empty_blocks from dba_tables where table_name=‘EMPLX‘;

TABLE_NAME      TABLESPACE_NAME     BLOCKS EMPTY_BLOCKS
--------------- --------------- ---------- ------------
EMPLX           LXTBS2                  23            0

#删除操作,
SQL> delete from emplx;

3584 rows deleted.

SQL> commit;

Commit complete.
#delete删除所有数据后没有降低高水位线,并不会降低全表扫描的代价
SQL> select table_name,tablespace_name,blocks, empty_blocks from dba_tables where table_name=‘EMPLX‘;

TABLE_NAME      TABLESPACE_NAME     BLOCKS EMPTY_BLOCKS
--------------- --------------- ---------- ------------
EMPLX           LXTBS2                  23            0

SQL> select * from emplx;

no rows selected


Execution Plan
----------------------------------------------------------
Plan hash value: 155704778

---------------------------------------------------------------------------
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |       |  3584 |   112K|     8   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| EMPLX |  3584 |   112K|     8   (0)| 00:00:01 |
---------------------------------------------------------------------------


#执行truncate操作:
SQL> truncate table emplx;

Table truncated.
#再对进行分析
SQL> analyze table emplx compute statistics;

Table analyzed.

#truncate降低高水位线,只剩余一个区,并且会降低全表扫描的代价
SQL>  select table_name,tablespace_name,blocks, empty_blocks from dba_tables where table_name=‘EMPLX‘;

TABLE_NAME      TABLESPACE_NAME     BLOCKS EMPTY_BLOCKS
--------------- --------------- ---------- ------------
EMPLX           LXTBS2                   0            7



3.delete操作后降低表空间。(重点)
使用alter table emplx move 和alter table emplx  shrink space都可以用来进行段收缩,降低高水位线,也都可以用来消除行连接和行迁移。
①.使用alter table  move会把表最多收缩到创建表时的storage子句中指定的初始大小,使用later shrink space 不会受此限制。
②.使用alter table move 之后,索引会无效,需要重建,使用alter table shrink space 则不会。
③.只能在表所在的表空间是自动段管理(ASSM)的时候,才能使用alter table shrink space; 而move在自动段管理(ASSM)和手动段管理(MSSM)方式下都能使用。
④.可以使用alter table shrink space compact来对表进行碎片整理,而不调整高水位线,之后再次调用alter table shrink space 来释放空间。
⑤.可以使用alter table shrink space cascade;指定了cascade,则收缩行为将级联到所有支持收缩操作的从属段,但是 物化视图、LOB索引、和IOT表例外;
⑥.move 更快 shrink space 较慢。

alter table emplx move 和alter table emplx  shrink space使用:在MSSM管理的表空间上创建EMPLX表

SQL> select table_name,tablespace_name, blocks,empty_blocks from dba_tables where table_name=‘EMPLX‘;

TABLE_NAME   TABLESPACE_NAME                    BLOCKS EMPTY_BLOCKS
------------ ------------------------------ ---------- ------------
EMPLX        LXTBS2                                  0            7


#插入数据
SQL> insert into emplx select * from emplx;

1792 rows created.
#分析表
SQL> analyze table emplx compute statistics;

Table analyzed.

SQL> select table_name,tablespace_name, blocks,empty_blocks from dba_tables where table_name=‘EMPLX‘;

TABLE_NAME   TABLESPACE_NAME                    BLOCKS EMPTY_BLOCKS
------------ ------------------------------ ---------- ------------
EMPLX        LXTBS2                                 23            0
 #删除数据
SQL> delete from emplx where rownum <=2000;

2000 rows deleted.

SQL> commit;

Commit complete.

SQL>  select table_name,tablespace_name, blocks,empty_blocks from dba_tables where table_name=‘EMPLX‘;

TABLE_NAME   TABLESPACE_NAME                    BLOCKS EMPTY_BLOCKS
------------ ------------------------------ ---------- ------------
EMPLX        LXTBS2                                 23            0
#使用shrink space 的前奏
SQL> alter table  emplx enable row movement ;

Table altered.
#使用shrink space降低高水位线,报错,因为在shrink space只能使用在assm管理段空间方式的表空间上。
SQL> alter table emplx shrink space;
alter table emplx shrink space
*
ERROR at line 1:
ORA-10635: Invalid segment or tablespace type

#使用move降低高水位线
SQL> alter table emplx move;

Table altered.
#分析表
SQL> analyze table emplx compute statistics;

Table analyzed.
#查看块的使用情况
SQL>  select table_name,tablespace_name, blocks,empty_blocks from dba_tables where table_name=‘EMPLX‘;

TABLE_NAME   TABLESPACE_NAME                    BLOCKS EMPTY_BLOCKS
------------ ------------------------------ ---------- ------------
EMPLX        LXTBS2                                 10            5












【oracle11g,17】存储结构: 段的类型,数据块(行连接、行迁移,块头),段的管理方式,高水位线

上一篇:Oracle 存储过程 返回结果集


下一篇:数据库内置视图或者表结构在开发中的使用场景