管理和維護表

 

 第六章:管理和維護表
 
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;
這是一個代價比較大的操作,要求有較大的臨時表空間和排序區
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章