天天看點

truncate分區表的操作,會導緻全局索引失效?

今天看到《删除分區如何不讓全局索引失效?》這篇文章有朋友提了個問題,

truncate分區表的操作,會導緻全局索引失效?

truncate是删除資料操作,但他是DDL語句,不是delete這種DML語句,不會寫redo和undo,不能rollback。

官方文檔,已經明确指出,除非使用update indexes,否則用truncate分區表,就會導緻全局索引失效,必須重建,

Unless you specify UPDATE INDEXES, any global indexes are marked UNUSABLE and must be rebuilt. (You cannot use UPDATE INDEXES for index-organized tables. Use UPDATE GLOBAL INDEXES instead.)

在alter table分區表的操作中帶着update indexes,就會讓Oracle在執行DDL語句的同時,更新索引,當然這會讓alter table執行的時間更長。這就是所謂“甘蔗沒有兩頭甜”。

擴充一下,對堆表來說,alter table不帶update indexes,則涉及的局部索引會失效,涉及的全局索引會标記為失效,需要重建,對索引組織表,局部索引的效果和堆表相同,但是全局索引仍可用,

truncate分區表的操作,會導緻全局索引失效?

分區表執行drop、truncate、exchange這些DDL操作,不再是快速操作,他的時間就需要衡量了,因為會導緻全局索引的失效,需要重建索引,

The DROP, TRUNCATE, and EXCHANGE operations are no longer fast operations. Again, you must compare the time it takes to do the DDL and then rebuild all indexes.

最簡單的方式,當然就是測試,實踐是檢驗真理的唯一标準。

建立測試表、測試資料,

SQL> CREATE TABLE interval_sale
  2      ( prod_id        NUMBER(6)
  3      , cust_id        NUMBER
  4      , time_id        DATE
  5      )
  6      PARTITION BY RANGE (time_id)
  7      INTERVAL(NUMTOYMINTERVAL(1, 'YEAR'))
  8        ( PARTITION p0 VALUES LESS THAN (TO_DATE('1-1-2003', 'DD-MM-YYYY')),
  9          PARTITION p1 VALUES LESS THAN (TO_DATE('1-1-2004', 'DD-MM-YYYY')),
 10         PARTITION p2 VALUES LESS THAN (TO_DATE('1-1-2005', 'DD-MM-YYYY')),
 11         PARTITION p3 VALUES LESS THAN (TO_DATE('1-1-2006', 'DD-MM-YYYY')));
Table created.


SQL> insert into interval_sale values(1, 1, to_date('2002-01-01','yyyy-mm-dd'));
1 row created.


SQL> insert into interval_sale values(2, 2, to_date('2003-01-01','yyyy-mm-dd'));
1 row created.


SQL> insert into interval_sale values(3, 3, to_date('2004-01-01','yyyy-mm-dd'));
1 row created.


SQL> insert into interval_sale values(4, 4, to_date('2005-01-01','yyyy-mm-dd'));
1 row created.


SQL> commit;
Commit complete.           

複制

建立全局索引,

SQL> create index idx_01 on interval_sale(cust_id);


Index created.


SQL> select table_name, index_name, partitioned, status from user_indexes where table_name='INTERVAL_SALE';


TABLE_NAME       INDEX_NAME     PAR  STATUS
--------------- --------------- --- --------
INTERVAL_SALE      IDX_01       NO    VALID           

複制

執行truncate,不帶update indexes,

SQL> alter table interval_sale truncate partition p1;
Table truncated.           

複制

此時索引狀态,UNUSABLE,

SQL> select table_name, index_name, partitioned, status from user_indexes where table_name='INTERVAL_SALE';
TABLE_NAME       INDEX_NAME   PAR  STATUS
--------------- ------------- --- --------
INTERVAL_SALE    IDX_01       NO  UNUSABLE           

複制

如果用了update indexes,全局索引狀态,仍是VALID,

SQL> alter table interval_sale truncate partition p3 update indexes;
Table truncated.


SQL> select table_name, index_name, partitioned, status from user_indexes where table_name='INTERVAL_SALE';
TABLE_NAME        INDEX_NAME   PAR  STATUS
---------------- ------------- --- --------
INTERVAL_SALE       IDX_01     NO   VALID           

複制

當然,按照《删除分區如何不讓全局索引失效?》邏輯,執行delete,再執行truncate,

SQL> delete from interval_sale partition (p0);
2 rows deleted


SQL> alter table interval_sale truncate partition p0;                    
Table truncated.           

複制

此時全局索引狀态還是VALID,但是這種操作,沒什麼實際意義,

SQL> select table_name, index_name, partitioned, status from user_indexes where table_name='INTERVAL_SALE';
TABLE_NAME       INDEX_NAME   PAR  STATUS
--------------- ------------- --- --------
INTERVAL_SALE      IDX_01     NO   VALID           

複制

bisal 部落格專家

釋出了512 篇原創文章 · 獲贊 492 · 通路量 200萬+