12c: ‘update global indexes’ enfin très rapide sur drop et truncate

On partitionne les tables pour 2 raisons:

  • Performance: aller lire un plus petit segment en full scan, ou un plus petit index local grâce au partition pruning
  • Maintenabilité: faire des opérations de purge, archivage, reorganisation, voir chargement (avec exchange partition) de manière très facile

Mais toutes les requêtes ne font pas de partition pruning, et on est amené créer des index globaux pour des raisons de performances. Mais alors on perd de la maintenabilité: les opérations sur les partitions vont:

  • soit rendre l’index unusable, qu’il faudra rebuilder complètement. Ce n’est pas acceptable lorsque notre maintenance ne touchait qu’une partition parmi beaucoup d’autres
  • soit utiliser ‘update global indexes’ pour maintenir l’index au fur et à mesure. Mais l’opération devient alors très longue.

Et pourtant, s’il s’agit d’un DROP PARTITION ou TRUNCATE PARTITION, cette maintenance d’index consiste seulement à nettoyer les entrées d’index qui deviennent orphelines (i.e qui adressent un rowid qui n’existe plus).

Alors la 12c a optimisé cela en faisant l’opération en 2 temps, utilisant la fonctionnalité ‘Asynchronous Global Index Maintenance’ ou ‘Fast Index maintenance':

  1. un ALTER TABLE … DROP/TRUNCATE PARTITION UPDATE GLOBAL INDEXES
  2. ne va pas toucher aux index globaux. Il va seulement enregistrer le data_object_id du segment qu’on vient de supprimer (un truncate ne supprime pas vraiement le segment, mais en change son data_object_id ce qui revient au même logiquement). C’est enregistré dans la table du dictionnaire SYS.INDEX_ORPHANED_ENTRY$.

  3. les requêtes qui lisent l’index chargent ces infos pour ignorer tous les rowid qui référencent ce data_object_id
  4. un job automatique (un de plus) va faire le nettoyage de manière asynchrone

On peut faire ce nettoyage nous même avec

ALTER INDEX ... COALESCE CLEANUP;

mais aussi appeler

exec dbms_part.cleanup_gidx;

qui va faire ce coalesce sur tous les index référencés par

SYS.INDEX_ORPHANED_ENTRY$

Différentes variations dans la demo.
Le cleanup peut charger la machine, c’est peut-être mieux de l’anticiper à un moment de faible charge plutôt que de le laisser tourner à 2 heures du matin comme c’est planifié par défaut.

C’est une amélioration importante: en Entreprise Edition, il n’y a plus à hésiter pour partitionner les tables qui grossissent afin que l’augmentation du volume de l’historique ne pénalise pas les performances. Sans avoir peur de définir trop d’index global. Une fois partitionné, ce sera facile de maintenir les plus anciennes partitions: purger, archiver, déplacer sur des tablespaces (move online en 12c) qui sont sur des disques moins chers. Et plus on laisse les tables grossir, plus l’opération de partitionnement sera compliquée !