Range Partitioning et Null

Hors contexte, cet article n’a pas beaucoup de sens ! Pourquoi utiliser la valeur NULL dans une clé de partitionnement ? Evidemment, il ne s’agit pas d’encourager qui que ce soit à ce genre de pratiques ; ou au moins, il ne s’agit pas de l’encourager, plus que ça.

Oracle n’interdit pas d’utiliser NULL dans une clé de partitionnement. Et comme ça n’est pas interdit, attendez-vous à ce que ce soit utilisé. En fait, il y a au moins 2 bonnes raisons à cette utilisation auxquelles je peux penser :

  • Une erreur
  • L’utilisation de clés multi-colonnes comme clé de partitionnement ; j’en reparlerai bientôt

Cet article illustre comment gérer une table partitionnée avec des clés de partitionnement NULL.

Contexte

Commençons par un petit rappel sur l’utilisation du partitioning. Soit une table partitionnée par RANGE :

create table T1(mydate    date,

othercols number)
partition by range(mydate)
(partition data2010
values less than (to_date('01/01/2011','DD/MM/YYYY')));

Vous ne pouvez pas insérer de données dont la partition correspondante n’existe pas. Voici un exemple :

insert into t1

values (to_date('01/01/2011','DD/MM/YYYY'), 1);

*
ERROR at line 1:
ORA-14400: inserted partition key does not map to any partition

Pour éviter ce problème, vous effectuerez des opérations de maintenance régulière (et sans doute automatiques) pour créer les partitions par anticipation :

alter table T1

add partition data2011
values less than (to_date('01/01/2012','DD/MM/YYYY'));

insert into t1
values (to_date('01/01/2011','DD/MM/YYYY'), 1);

Ainsi naquit le partitionnement par Intervalle

Reprenons au début ; si vous ne voulez pas effectuer de maintenance (même automatique), créez simplement un partitionnement par Intervalle. Les partitions seront créées automatiquement :

drop table T1 purge;

create table T1(mydate date,
othercols number)
partition by range(mydate) interval(numtoyminterval(1,'YEAR'))
(partition data2010 values less than (to_date('01/01/2011','DD/MM/YYYY')));

insert into t1
values (to_date('01/01/2011','DD/MM/YYYY'), 1);

commit;

Et NULL alors ?

Seulement voilà, dans le cas d’un partitionnement par Intervalle, si vous tentez d’insérer NULL, la punition est presque la même que dans le cas d’une valeur inexistante ; remarquez la petite nuance :

insert into t1

values (null, 2);
*
ERROR at line 1:
ORA-14300: partitioning key maps to a partition outside maximum permitted
number of partitions

Et pourtant, on peut mettre NULL

Mais revenons à nos partitions gérées à la main :

drop table T1 purge;

create table T1(mydate date,
othercols number)
partition by range(mydate)
(partition data2010
values less than (to_date('01/01/2011','DD/MM/YYYY')));

Pour illustrer que, dans le monde d’avant, MAXVALUE permet de créer des partitions qui stockent les NULL :

alter table T1 add partition dataothers values less than (MAXVALUE);

insert into T1 values (null, 2);
commit;
select count(*) from T1 partition(dataothers);
COUNT(*)
--------
1

Dans ce cas, pour ajouter des partitions, il faudra passer par la commande SPLIT PARTITION plutôt qu’un ADD PARTITION :

alter table T1 split partition dataothers

at (to_date('01/01/2012','DD/MM/YYYY'))
into (partition data2011, partition dataothers)
update global indexes;

Partitioning List et Hash

Vous vérifierez avec les partitioning List et Hash, vous pouvez également stocker les valeurs NULL :

drop table T1 purge;

create table T1(mydate date,
othercols number)
partition by hash(mydate) partitions 2;

insert into T1 values (null,1);

commit;

drop table T1 purge;
create table T1(mydate date,
othercols number)
partition by list(mydate)
(partition p1 VALUES (null));

insert into T1 values (null,1);

commit;

drop table T1 purge;

Une preuve de plus que, même quand on pense avoir pensé à tout, il en manque…

1 réflexion sur “Range Partitioning et Null”

  1. This post was very useful for me to solve a problem. Thanks a lot!!

    Rubem Costa
    Brazil

Les commentaires sont fermés.