partitioning bằng DBMS_REDEFINITION

Bạn có thể xem phiên bản youtube của bài viết tại đây:

   Giới thiệu

 

Để chuyển đổi 1 bảng bình thường (non-partition) sang bảng partition, chúng ta có thể có nhiều cách.

 

Trong bài viết này tôi sẽ hướng dẫn các bạn cách sử dụng thủ tục DBMS_REDEFITION để thực hiện điều này nhé.

 

Cách làm này có ưu điểm lớn nhất là:

 

Trong quá trình chuyển đổi bảng từ non-partition sang partition, bạn vẫn thao tác select, insert, update, delete bình thường, như không có gì xảy ra!

 

Chú ý: Cách làm này chỉ áp dụng với các bảng không thuộc sở hữu của user SYS thôi nhé.

 

Liên quan đến chủ đề partitioned table, nếu bạn chưa biết nó là gì, có thể tham khảo bài viết sau của tôi:

 

Đọc thêm  Kiến thức cơ bản về partitioned table

 


 

   Cách làm

 

   Tạo môi trường test:

 

Tạo bảng INVOICES là bảng non-partition

 

CREATE TABLE DUY.INVOICES
(invoice_no    NUMBER PRIMARY KEY,
 invoice_date  DATE   NOT NULL,
 comments      VARCHAR2(500));

 

Thêm 1 chút dữ liệu để test

 

INSERT INTO DUY.INVOICES VALUES (1, '01-Mar-2021', 'Quarter 1');
INSERT INTO DUY.INVOICES VALUES (2, '11-Jul-2021', 'Quarter 2');
INSERT INTO DUY.INVOICES VALUES (3, '15-Sep-2021', 'Quarter 3');
INSERT INTO DUY.INVOICES VALUES (4, '21-Nov-2021', 'Quarter 4');
COMMIT;

 

Tạo bảng INVOICES2 là bảng partition với các cột và data type giống hệt INVOICES, nhưng bảng INVOICES2 là bảng partition

 

CREATE TABLE invoices2
(invoice_no    NUMBER PRIMARY KEY,
 invoice_date  DATE   NOT NULL,
 comments      VARCHAR2(500))
PARTITION BY RANGE (invoice_date)
(PARTITION invoices_q1 VALUES LESS THAN (TO_DATE('01/04/2021', 'DD/MM/YYYY')),
 PARTITION invoices_q2 VALUES LESS THAN (TO_DATE('01/07/2021', 'DD/MM/YYYY')),
 PARTITION invoices_q3 VALUES LESS THAN (TO_DATE('01/09/2021', 'DD/MM/YYYY')),
 PARTITION invoices_q4 VALUES LESS THAN (TO_DATE('01/01/2022', 'DD/MM/YYYY')));

 

   Kiểm tra xem có thể dùng DBMS_REDEFINITION được hay không

 

BEGIN
   SYS.DBMS_REDEFINITION.can_redef_table (
      uname          => 'DUY',
      tname          => 'INVOICES',
      options_flag   => DBMS_REDEFINITION.CONS_USE_ROWID);
END;
/

 

Nếu kết quả không xuất hiện lỗi gì, có output như sau thì có nghĩa là bảng INVOICES có thể áp dụng DBMS_REDEFINITION để chuyển dữ liệu sang bảng INVOICES2 được.

 

PL/SQL procedure successfully completed.

 

   Bắt đầu đồng bộ dữ liệu 

 

Quá trình đồng bộ dữ liệu có thể kéo dài rất lâu. Bạn nên thực hiện các câu lệnh sau để tăng luồng xử lý, tăng tốc độ đồng bộ:

 

ALTER SESSION FORCE PARALLEL DML PARALLEL 16;
ALTER SESSION FORCE PARALLEL QUERY PARALLEL 16;

 

Sau đó, bạn thực hiện câu lệnh sau:

 

BEGIN
   SYS.DBMS_REDEFINITION.start_redef_table (uname        => 'DUY',
                                            orig_table   => 'INVOICES',
                                            int_table    => 'INVOICES2');
END;
/

 

Thủ tục DBMS_REDEFINITION sẽ bắt đầu chuyển dữ liệu hiện có tại INVOICES sang INVOICES2.

 

   Copy các đối tượng liên quan đến bảng sang bảng mới

 

Thủ tục dưới đây sẽ copy các index, trigger, constraint, privileges trên bảng gốc và chuyển sang bảng mới.

 

DECLARE
  num_errors PLS_INTEGER;
BEGIN
  DBMS_REDEFINITION.copy_table_dependents(
    uname             => 'DUY',
    orig_table        => 'INVOICES',
    int_table         => 'INVOICES2',
    copy_indexes      => DBMS_REDEFINITION.cons_orig_params,
    copy_triggers     => TRUE, 
    copy_privileges   => TRUE, 
    ignore_errors     => FALSE,
    num_errors        => num_errors); 
END;
/

 

   Đồng bộ dữ liệu sinh ra trong quá trình chuyển đổi

 

Bạn thực hiện thủ tục sau để đồng bộ những dữ liệu mới được sinh ra trong khoảng thời gian chuyển dữ liệu này sang bảng mới

 

BEGIN
   DBMS_REDEFINITION.sync_interim_table (uname        => 'DUY',
                                         orig_table   => 'INVOICES',
                                         int_table    => 'INVOICES2');
END;
/

 

   Kết thúc quá trình đồng bộ

 

Bạn thực hiện câu lệnh sau để kết thúc toàn bộ thủ tục chuyển đổi:

 

BEGIN
   DBMS_REDEFINITION.finish_redef_table (uname        => 'DUY',
                                         orig_table   => 'INVOICES',
                                         int_table    => 'INVOICES2');
END;
/

 

Ở bước này bảng INVOICES2 và INVOICE sẽ tráo đổi tên cho nhau. 

 

Như vậy, bảng INVOICES lúc này sẽ là bảng partition. Còn bảng INVOICES2 lại là bảng non-partition.

 


 

   Kiểm tra lại:

 

   Kiểm tra kiểu của bảng là non-partition hay partition

 

select table_name, PARTITIONED from dba_tables where owner='DUY';

 

Kết quả là:

 

TABLE_NAME    PARTITIONED
-----------   -----------
INVOICES2     NO
INVOICES      YES

 

   Kiểm tra dữ liệu của bảng có đầy đủ hay không

 

select * from duy.invoices;

 

Kết quả:

 

INVOICE_NO INVOICE_D COMMENTS
---------- --------- ------------------------------
         1 01-MAR-21 Quarter 1
         2 11-JUL-21 Quarter 2
         3 15-SEP-21 Quarter 3
         4 21-NOV-21 Quarter 4

 

Như vậy tôi đã hướng dẫn các bạn chuyển đổi 1 bảng non-partition sang partition bằng phương pháp DBMS_REDEFINITION.

 

Hẹn gặp lại các bạn vào các bài viết tiếp theo.

 

Nguồn: https://dangxuanduy.com/

 

Hiện tại, tôi có tổ chức đều đặn các khóa học về quản trị Oracle Database, tôi sẽ để thông tin ở đây, để bạn nào quan tâm về lịch học cũng như chương trình học có thể theo dõi nhé.

 

    KHÓA HỌC: QUẢN TRỊ ORACLE DATABASE THẬT LÀ ĐƠN GIẢN  Xem ngay!

 

   Hãy tham gia group “Kho tài liệu kiến thức database” để cùng học hỏi và chia sẻ nhé.

 

Đặng Xuân Duy

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *