管理和维护表

 

 第六章:管理和维护表
 
6.1.表的概述;
    标量数据类型;
    集合数据类型;
    关系数据类型;
    ROWID;可以唯一标识行,可以快速找到一行数据;
6.2.创建表;
    6.2.1.创建普通表;
    6.2.2.创建临时表;
6.3.维护参数;(切记参数之间的相互关联性)
    6.3.1.创建表时用的参数一般不要改动;
    6.3.2.管理和控制数据块引入参数:
     INTRANS;概念:
事务槽---事务槽在数据块头中,存储了有关事务的控制信息,而每行数据有一个锁位,该锁位和事务槽号相同,数据块服务器就是通过每行的锁位找到数据块头中的事务槽,利用存储在该事务槽中的事务信息完成对该行数据的操作每个事务只能使用一个事务槽。
      Intrans定义了创建数据块时事务槽的初始值,该参数默认值为1.
     MAXTRANS;创建数据块时事务槽的最大值,默认255.
     PCTFREE;每个数据块预留空间的百分比数。默认10%。
数据块:数据块头+空闲区+数据区。为了留点空闲区为后续修改等操作准备,避免占用其他数据块的空间带来的磁盘I/O的效率低下。
     FREELISTS
      PCTUSED;数据块已经使用的空间的百分比数。默认值40%。
pctfree参数是控制Freelist un-links的(即将块由Freelists中移除)。设置pctfree=10意味着每个块都保留10%的空间用作行扩展。pctused参数是控制Freelist re-links的。设置pctused=40意味着只有在块的使用低于40%时才会回到表格的Freelists中。
 
6.4.维护列;
    插入列:alter table scott.employee
            Add(
                Sex char
);
    修改列:
        Alter table scott.employees
        MODIFY
        (degree varchar2(10) not null
        );
删除列:
    Alter table tablename drop column cloumnname cascade constraints;
    cascade constraints外键时。
    可以先将列设置成unused(不能再恢复),再删除。
更改列名:alter table scott.emp rename column sal to slary;
6.5.删除和截断表;
    Drop table;删除表及表结构
    TRUNCATE TABLE;删除数据保留表结构;
切记上面都无法恢复。
TRUNCATE和DELETE有以下几点区别
1、TRUNCATE在各种表上无论是大的还是小的都非常快。如果有ROLLBACK命令DELETE将被撤销,而TRUNCATE则不会被撤销。
2、TRUNCATE是一个DDL语言,向其他所有的DDL语言一样,他将被隐式提交,不能对TRUNCATE使用ROLLBACK命令。
3、TRUNCATE将重新设置高水平线和所有的索引。在对整个表和索引进行完全浏览时,经过TRUNCATE操作后的表比DELETE操作后的表要快得多。
4、TRUNCATE不能触发任何DELETE触发器。
5、不能授予任何人清空他人的表的权限。
6、当表被清空后表和表的索引讲重新设置成初始大小,而delete则不能。
7、不能清空父表。
6.6.分区表;     
 
    6.6.1分区表概念;
       由于将数据分散到各个分区中,减少了数据损坏的可能性;
可以对单独的分区进行备份和恢复;
可以将分区映射到不同的物理磁盘上,来分散IO;
提高可管理性、可用性和性能。
 
    6.6.2分类:
       范围分区;创建一个按字段数据范围分区的表,分区置于指定的不同表空间中
       示例代码:
--为各个分区准备独立的表空间
create tablespace test_space01 datafile‘d:/tbs01.dbf’ size 50m
create tablespace test_space02 datafile‘d:/tbs02.dbf’ size 50m
create tablespace test_space03 datafile‘d:/tbs03.dbf’ size 50m
create tablespace test_space04 datafile‘d:/tbs04.dbf’ size 50m
--创建分区表,
CREATE TABLE range_example(
     range_key_column DATE,
           DATA VARCHAR2(20),
           ID integer
)
PARTITION BY RANGE(range_key_column)
(  
PARTITION part01 VALUES LESS THAN(TO_DATE('2008-07-01 00:00:00','yyyy-mm-dd hh24:mi:ss')) TABLESPACEtest_space01,
PARTITION part02 VALUES LESS THAN(TO_DATE('2008-08-01 00:00:00','yyyy-mm-dd hh24:mi:ss')) TABLESPACE test_space02,
PARTITION part03 VALUES LESS THAN(TO_DATE('2008-09-01 00:00:00','yyyy-mm-dd hh24:mi:ss')) TABLESPACE test_space03,
PARTITION part04 VALUES LESS THAN (MAXVALUE)TABLESPACE test_space04
);
--插入测试数据
insert into range_examplevalues(TO_DATE('2008-06-10 00:00:00','yyyy-mm-dd hh24:mi:ss'), '1111', 1);
insert into range_examplevalues(TO_DATE('2008-07-20 00:00:00','yyyy-mm-dd hh24:mi:ss'), '2222', 2);
insert into range_examplevalues(TO_DATE('2008-08-25 00:00:00','yyyy-mm-dd hh24:mi:ss'), '3333', 3);
commit;
--在表上执行查询
select * from range_example;
--在表分区上执行查询
select * from range_example partition(part01);
      
    列表分区;该分区的特点是某列的值只有几个,基于这样的特点我们可以采用列表分区
    例一
CREATE TABLE PROBLEM_TICKETS
(
    PROBLEM_ID   NUMBER(7) NOT NULL PRIMARY KEY,
    DESCRIPTION VARCHAR2(2000),
    CUSTOMER_ID NUMBER(7) NOT NULL,
    DATE_ENTERED DATE NOT NULL,
    STATUS VARCHAR2(20)
)
PARTITION BY LIST (STATUS)
(
      PARTITION PROB_ACTIVE   VALUES ('ACTIVE') TABLESPACE PROB_TS01,
      PARTITION PROB_INACTIVE VALUES ('INACTIVE') TABLESPACE PROB_TS02
    )
例二
CREATE TABLE ListTable
(
    id INT PRIMARY KEY ,
    name VARCHAR (20),
    area VARCHAR (10)
)
PARTITION BY LIST (area)
(
    PARTITION part1 VALUES ('guangdong','beijing') TABLESPACE Part1_tb,
    PARTITION part2 VALUES ('shanghai','nanjing') TABLESPACE Part2_tb
);
)
       Hash分区;
hash分区最主要的机制是根据hash算法来计算具体某条纪录应该插入到哪个分区中,hash算法中最重要的是hash函数,Oracle中如果你要使用hash分区,只需指定分区的数量即可。建议分区的数量采用2的n次方,这样可以使得各个分区间数据分布更加均匀。
CREATE TABLE emp
(
    empno NUMBER (4),
    ename VARCHAR2 (30),
    sal   NUMBER
)
PARTITION BY HASH (empno)
PARTITIONS 8-----8个表空间循环存储数据
STORE IN (emp1,emp2,emp3,emp4,emp5,emp6,emp7,emp8);
       复合分区;
    create table dinya_test
    (
    transaction_id number primary key,
 item_id number(8) not null,
 item_description varchar2(300),
 transaction_date date
    )
partition by range(transaction_date)subpartition by hash(transaction_id) subpartitions 3 store in (dinya_space01,dinya_space02,dinya_space03)
    (
     partition part_01 values less than(to_date(‘2006-01-01’,’yyyy-mm-dd’)),
     partition part_02 values less than(to_date(‘2010-01-01’,’yyyy-mm-dd’)),
     partition part_03 values less than(maxvalue)
 );
6.7.分区表维护:
    Oracle 分区表维护
建立实验表和索引
 
SQL> Create Table t(owner, object_name, subobject_name, object_id, data_object_id, object_type, created,
 
                                     last_ddl_time, timestamp, status, temporary, generated, secondary)
      Partition By Range(object_id)
        (Partition p_3000 Values Less Than(3000) Tablespace users,
         Partition p_6000 Values Less than(6000) Tablespace users,
         Partition p_max Values less than(maxvalue) tablespace users
         )
     As
     Select owner, object_name, subobject_name, object_id, data_object_id, object_type, created,
                    last_ddl_time, timestamp, status, temporary, generated, secondary
          From dba_objects;
SQL> create index idx_global_t_object_id on t(owner) global;
SQL> create index idx_local_t_object_id on t(object_id) local;
 
    主要的分区维护操作
1.新增分区
如果分区边界不是maxvalue,那么可以直接add一个新的分区,如果边界是maxvalue,则需要先drop掉原有分区,然后再add,或者采用分区的拆分split
SQL> alter table t drop partition p_max;
Table altered
SQL> alter table t add partition p_9000 values less than(9000) tablespace users;
对于局部索引,oracle会自动增加一个局部分区索引。
2.移动分区
SQL> alter table t move partition p_6000 tablespace system;
Table altered
SQL> Select index_name,status From user_indexes Where table_name='T';
INDEX_NAME                    STATUS
------------------------------ --------
IDX_GLOBAL_T_OBJECT_ID        UNUSABLE
IDX_LOCAL_T_OBJECT_ID         N/A
分区移动会自动维护局部分区索引,oracle不会自动维护全局索引,所以需要我们重新rebuild分区索引,具体需要rebuild哪些索引,可以通过dba_part_indexes,dba_ind_partitions去判断。
3.截断分区
SQL> alter table t truncate partition p_3000 ;
Table truncated
SQL> Select index_name,status From user_indexes Where table_name='T';
INDEX_NAME                    STATUS
------------------------------ --------
IDX_GLOBAL_T_OBJECT_ID        UNUSABLE
IDX_LOCAL_T_OBJECT_ID         N/A
 
Truncate相对delete操作很快,数据仓库中的大量数据的批量数据加载可能会有用到;截断分区同样会自动维护局部分区索引,同时会使全局索引unusable,需要重建
4. Drop分区
SQL> alter table t drop partition p_6000;
Table altered
同样会自动维护局部分区索引,同时会使全局索引unusable,需要重建
5. 分区拆分split
通过user_tab_partitions视图来看table有哪些分区
SQL> Select table_name,partition_name From user_tab_partitions Where table_name='T';
TABLE_NAME                    PARTITION_NAME
------------------------------ ------------------------------
T                             P_3000
T                             P_9000
T                             P_MAX
现在想要把p_9000分区分成p_6000,用户存放object_id >=3000 and object_id<6000,p_9000用户存放object_id>=6000 and object_id<9000的记录,利用split技术,就可以实现
 
SQL> alter table tsplit partitionp_9000 at(6000) into (partitionp_6000 tablespace users,partitionp_9000 tablespace system);
SQL>
SQL> Select table_name,partition_name From user_tab_partitions Where table_name='T';
TABLE_NAME                    PARTITION_NAME
------------------------------ ------------------------------
T                             P_3000
T                             P_6000
T                             P_9000
T                             P_MAX
SQL> Select Max(object_id) ,Min(object_id) From t Partition (p_6000);
MAX(OBJECT_ID) MIN(OBJECT_ID)
-------------- --------------
         5999          3000
 
SQL> Select Max(object_id) ,Min(object_id) From t Partition (p_9000);
MAX(OBJECT_ID) MIN(OBJECT_ID)
-------------- --------------
         8999          6000
对于剧本索引IDX_LOCAL_T_OBJECT_ID,通过查看user_ind_partitions ,可以看到split后会自动一个局部分区索引,索引名字等同于新增分区的名字,全局索引会失效,需要rebuild。
 6. 分区合并merge
 相邻的分区可以merge为一个分区,新分区的下边界为原来边界值较低的分区,上边界为原来边界值较高的分区,原先的局部索引相应也会合并,全局索引会失效,需要rebuild。
SQL> alter table t merge partitions p_6000,p_9000 into partition p_9000;
Table altered
SQL> Select table_name,partition_name From user_tab_partitions Where table_name='T';
TABLE_NAME                    PARTITION_NAME
------------------------------ ------------------------------
T                             P_3000
T                             P_9000
T                             P_MAX
 
SQL> Select Max(object_id) ,Min(object_id) From t Partition (p_9000);
MAX(OBJECT_ID) MIN(OBJECT_ID)
-------------- --------------
8999     3000
7. 分区交换exchange
分区的交换可以把一个表和分区表中的一个分区中的数据进行对换,分区的交换只是一个数据字典的操作,因此操作速度很快,对于数据仓库中的load阶段,因为已经做了数据的清洗动作,还可以用without validation来避免对表中数据的验证(需要全表扫描)
 
SQL> select count(*) from t partition(p_6000);
 COUNT(*)
----------
        0
SQL> create table t_6000 as select * from dba_objects where object_id>=3000 and object_id<6000;
SQL> alter table t exchange partition p_6000 with table t_6000;
SQL> select count(*) from t partition(p_6000);
 COUNT(*)
----------
     2955
 
SQL> select count(*) from t_6000;
 COUNT(*)
----------
        0
如果交换的表中包含的记录不符合分区的规定,那么可以用without validation子句跳过检查。
SQL> create table t_6000 as select * from dba_objects where object_id>=3000 and object_id<7000;
Table created
SQL> alter table t exchange partition p_6000 with table t_6000;
alter table t exchange partition p_6000 with table t_6000
ORA-14099:未对指定分区限定表中的所有行
SQL> alter table t exchange partition p_6000 with table t_6000 without validation;
Table altered
 
 
Exchange还有一个子句including indexes,指分区和表的索引相互交换,索引也可以交换,采用前面的例子,分区表有2个索引,一个在object_id列上的局部索引,一个是owner上的全局索引,实验在t_6000的object_id上建立所以,exchange可以完成,但在owner上,还是报错奥…
SQL>alter table t exchange partition p_6000 with table t_6000 including indexes without validation
ORA-14098: ALTER TABLE EXCHANGE PARTITION中的表索引不匹配
SQL> create index t_idx_object_owner on t_6000(owner);
建立所以后,交换成功。
SQL> drop index t_idx_object_id;
SQL> create index t_idx_object_owner on t_6000(owner);
SQL> alter table t exchange partition p_6000 with table t_6000 including indexes without validation ;
ORA-14098: ALTER TABLE EXCHANGE PARTITION中的表索引不匹配
添加分区实例
1.建表和相关索引
DROP TABLE SYSTEM.CUSTADDR CASCADE CONSTRAINTS;
CREATE TABLE SYSTEM.CUSTADDR
(
 ID         VARCHAR2(15 BYTE)                  NOT NULL,
 ADDRABB    VARCHAR2(100 BYTE)                 NOT NULL,
 TEAMID     VARCHAR2(20 BYTE),
 ADDRESS    VARCHAR2(150 BYTE),
 AREACODE   VARCHAR2(4 BYTE),
 ADDRONE    VARCHAR2(20 BYTE),
 ADDRTWO    VARCHAR2(20 BYTE),
 ADDRTHREE VARCHAR2(100 BYTE),
 ADDRFOUR   VARCHAR2(100 BYTE),
 COMPABB    VARCHAR2(100 BYTE),
 CUSTID     VARCHAR2(15 BYTE)                  NOT NULL
)
TABLESPACE SYSTEM
PCTUSED    40
PCTFREE    10
INITRANS   1
MAXTRANS   255
LOGGING
PARTITION BY LIST (AREACODE)
(
 PARTITION T_LIST556 VALUES ('556')
    LOGGING
    NOCOMPRESS
    TABLESPACE SYSTEM
    PCTUSED    40
    PCTFREE    10
    INITRANS   1
    MAXTRANS   255
    STORAGE    (
                INITIAL          64K
                MINEXTENTS       1
                MAXEXTENTS       UNLIMITED
                FREELISTS        1
                FREELIST GROUPS 1
                BUFFER_POOL      DEFAULT
               ),
   PARTITION P_OTHER VALUES (DEFAULT)
    LOGGING
    NOCOMPRESS
    TABLESPACE SYSTEM
    PCTUSED    40
    PCTFREE    10
    INITRANS   1
    MAXTRANS   255
    STORAGE    (
                INITIAL          64K
                MINEXTENTS       1
                MAXEXTENTS       UNLIMITED
                FREELISTS        1
                FREELIST GROUPS 1
                BUFFER_POOL      DEFAULT
               )
)
NOCOMPRESS
NOCACHE
NOPARALLEL
MONITORING;
CREATE INDEX SYSTEM.IX_CUSTADDR_ADDRABB_TP ON SYSTEM.CUSTADDR
(ADDRABB)
 INITRANS   2
 MAXTRANS   255
LOCAL (
 PARTITION T_LIST556
    LOGGING
    NOCOMPRESS
    TABLESPACE SYSTEM
    PCTFREE    10
    INITRANS   2
    MAXTRANS   255
    STORAGE    (
                INITIAL          64K
                MINEXTENTS       1
                MAXEXTENTS       UNLIMITED
                FREELISTS        1
                FREELIST GROUPS 1
                BUFFER_POOL      DEFAULT
               ),
 PARTITION P_OTHER
    LOGGING
    NOCOMPRESS
    TABLESPACE SYSTEM
    PCTFREE    10
    INITRANS   2
    MAXTRANS   255
    STORAGE    (
                INITIAL          64K
                MINEXTENTS       1
                MAXEXTENTS       UNLIMITED
                FREELISTS        1
                FREELIST GROUPS 1
                BUFFER_POOL      DEFAULT
               )
)
NOPARALLEL;
2. 添加新的分区
ALTER TABLE CUSTADDR DROP PARTITION P_OTHER;
ALTER TABLE CUSTADDR ADD PARTITION T_LIST558 VALUES ('558')
    LOGGING
    NOCOMPRESS
    TABLESPACE SYSTEM
    PCTUSED    40
    PCTFREE    10
    INITRANS   1
    MAXTRANS   255
    STORAGE    (
                INITIAL          64K
                MINEXTENTS       1
                MAXEXTENTS       UNLIMITED
                FREELISTS        1
                FREELIST GROUPS 1
                BUFFER_POOL      DEFAULT
               );
 ALTER TABLE CUSTADDR ADD PARTITION P_OTHER VALUES (DEFAULT)
    LOGGING
    NOCOMPRESS
    TABLESPACE SYSTEM
    PCTUSED    40
    PCTFREE    10
    INITRANS   1
    MAXTRANS   255
    STORAGE    (
                INITIAL          64K
                MINEXTENTS       1
                MAXEXTENTS       UNLIMITED
                FREELISTS        1
                FREELIST GROUPS 1
                BUFFER_POOL      DEFAULT
               );
3. 重建分区索引
对于local索引,每一个表分区对应一个索引分区,当表的分区发生变化时,索引的维护由Oracle自动进行。对于global索引,可以选择是否分区,而且索引的分区可以不与表分区相对应。当对分区进行维护操作时,通常会导致全局索引的INVALDED,必须在执行完操作后 REBUILD。
分区索引是不能整体重建的,不能用
SQL>alter index loc_xxxx_col rebuild;
可以指定分区进行重建:
SQL>alter index loc_xxxx_col rebuild partition 分区名 online;
使用online来尽可能减少创建过程中出现的任何加锁问题。
 
如果你要整体新建,必须先drop 原有分区索引,然后
SQL>create index loc_xxxx_col on xxxx(col) local tablespace SYSTEM;
这是一个代价比较大的操作,要求有较大的临时表空间和排序区
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章