Tables partitionnées, compression et DBMS_REDEFINITION

La base de données Oracle permet de redéfinir une partition en ligne et ainsi :

  • Changer ses propriétés de stockage comme le tablespace ou le paramètre pctfree
  • Compresser les données

Dans cet article, vous trouverez un exemple d’application de cette technique pour compresser une partition en ligne avec Oracle 11g Release 2. Si vous cherchez des informations plus générales sur DBMS_REDEFINITION, regardez les articles précédents qui regroupent un ensemble de questions/réponses sur le sujet et met en oeuvre un exemple avec toutes les requêtes associées

Préambule :
Avant de vous lancer, sachez qu’il y a plusieurs restrictions à l’utilisation de DBMS_REDEFINITION avec une partition ; reportez-vous à la documentation pour tous les détails concernant ces restrictions. Outre cela, vous noterez que :

  • Si vous avez des indexes bitmap sur la table et que vous voulez compresser la table, vous devrez déjà avoir au moins une partition compressée. Cette restriction est due au facteur de Hakan. Si ce n’est pas le cas, vous rencontrerez une erreur comme celle ci-dessous :

    *
    ERROR at line 1:
    ORA-42012: error occurred while completing the redefinition
    ORA-14642: Bitmap index mismatch for tables in ALTER TABLE EXCHANGE PARTITION
    ORA-06512: at "SYS.DBMS_REDEFINITION", line 78
    ORA-06512: at "SYS.DBMS_REDEFINITION", line 1664
    ORA-06512: at line 1

    ERROR at line 1:
    ORA-42012: error occurred while completing the redefinition
    ORA-14646: Specified alter table operation involving compression cannot be
    performed in the presence of usable bitmap indexes
    ORA-06512: at "SYS.DBMS_REDEFINITION", line 78
    ORA-06512: at "SYS.DBMS_REDEFINITION", line 1664
    ORA-06512: at line 1
  • Si vous n’avez pas de clé primaire sur la table, vous devrez avoir une licence Advanced Compression Option puisque il est impossible de supprimer une colonne d’une table compressée en mode normal et qu’avec le rowid, une colonne M_ROW$$ est créée sur la table intérimaire. Si vous tentez l’expérience malgré tout la « redefinition » échoue avec le message
    ERROR at line 1:
    ORA-42012: error occurred while completing the redefinition
    ORA-39726: unsupported add/drop column operation on compressed tables
    ORA-06512: at "SYS.DBMS_REDEFINITION", line 78
    ORA-06512: at "SYS.DBMS_REDEFINITION", line 1680
    ORA-06512: at line 1

Table d’exemple

Pour commencer, nous allons créer une table partitionnée et avec une partition compressée :

create table scott.x (x number,
y number,
attr1 number
)
partition by range (x)
(partition x1 values less than(10000) compress);

alter table scott.x
add partition x2 values less than(20000);

insert into scott.x values (1,1,1);
insert into scott.x values (10001,1,1);
commit;

create unique index scott.x_idx
on scott.x(x,y) local;

alter table scott.x
add constraint x_pk
primary key (x,y)
using index scott.x_idx;

create bitmap index scott.x_bidx
on scott.x(attr1) local;

Exemple d’utilisation de DBMS_REDEFINITION

Nous allons maintenant utiliser DBMS_REDEFINITION pour compresser la partition X2; Commençons par vérifier que la méthode peut être utilisée :

exec dbms_redefinition.can_redef_table(-
'SCOTT', -
'X', -
DBMS_REDEFINITION.CONS_USE_PK, -
'X2')

Créez une table intérimaire (compressée) et démarrez l’operation

create table SCOTT.X$INT (
x number,
y number,
attr1 number
) COMPRESS;

exec DBMS_REDEFINITION.START_REDEF_TABLE( -
'SCOTT', -
'X', -
'X$INT', -
COL_MAPPING => NULL, -
options_flag => DBMS_REDEFINITION.CONS_USE_PK, -
part_name=> 'X2')

Ajoutez les index et les contraintes sur la table

create unique index scott.x_idx$int
on scott.x$int(x,y);

alter table scott.x$int
add constraint x_pk$int
primary key (x,y)
using index scott.x_idx$int;

create bitmap index scott.x_bidx$int
on scott.x$int(attr1);

Synchronisez la table intérimaire puis terminez la redefinition :

exec dbms_redefinition.sync_interim_table(-
'SCOTT', -
'X', -
'X$INT', -
'X2')

exec dbms_redefinition.finish_redef_table(-
'SCOTT', -
'X', -
'X$INT', -
'X2')

Enfin supprimez la table intérimaire :

drop table scott.x$int cascade constraint purge;

En cas de problème

Vous pouvez annuler les opérations en cours et supprimer la table intérimaire

exec dbms_redefinition.abort_redef_table(-
'SCOTT', -
'X', -
'X$INT', -
'X2')

drop table SCOTT.X$INT cascade constraints purge;

Terminer votre exemple

Pour terminer, supprimer la table exemple :

drop table scott.x purge;