Oracle
 sql >> Base de données >  >> RDS >> Oracle

Partitionnement fractionné rapide

J'ai une table partitionnée pour certaines applications de journalisation. Il y a quelques années, j'ai partitionné la table avec une partition par mois. Alors que nous approchons de 2016, il est temps pour moi d'ajouter des partitions pour la nouvelle année. La table partitionnée a, comme ses deux dernières partitions, la partition de décembre 2015 et une partition utilisant MAXVALUE. Je n'ai jamais l'intention d'avoir des données dans la partition MAXVALUE. Il est juste là pour faciliter les opérations SPLIT PARTITION.

Dans le passé, j'ajoutais des partitions avec des commandes similaires à celles-ci :

ALTER TABLE usage_tracking
SPLIT PARTITION usage_tracking_pmax AT (TO_DATE('02/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS))
INTO (PARTITION usage_tracking_p201601, PARTITION usage_tracking_pmax);
ALTER TABLE usage_tracking
SPLIT PARTITION usage_tracking_pmax AT (TO_DATE('03/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS'))
INTO (PARTITION usage_tracking_p201602, PARTITION usage_tracking_pmax);

Les instructions SQL ci-dessus diviseront la partition MAXVALUE en deux partitions. Il existe 12 commandes de ce type, une pour chaque mois.

Cette année, lorsque j'ai essayé d'exécuter le script pour 2016 dans un environnement de non-production, j'ai été surpris de constater que ces commandes prenaient environ 30 minutes pour chacune. Les années précédentes, ils terminaient en quelques secondes. N'oubliez pas que USAGE_TRACKING_PMAX est vide, donc aucune donnée n'a besoin d'être déplacée vers une partition appropriée.

En analysant l'activité de ma session effectuant le SPLIT, je pouvais clairement voir les événements d'attente de fichier db qui étaient suivis dans cette table partitionnée. Il était évident que l'opération SPLIT lisait la partition max, même si elle était vide.

Les années précédentes fonctionnaient bien, mais cette base de données a récemment été mise à niveau vers Oracle 12c. J'ai trouvé des informations sur la façon d'effectuer une opération de partition fractionnée rapide dans la note MOS 1268714.1 qui indique que cela s'applique à Oracle 10.2.0.3 et supérieur, mais je n'ai rencontré aucun problème dans 11.2.0.4. C'était probablement juste une chance stupide et je n'ai pas de base de données 11g pour vérifier cela car tous les miens ont été mis à jour. En tant que tel, plutôt que de me concentrer sur ce qui a changé, je vais simplement résoudre le problème et continuer ma journée.

Selon la note MOS, pour effectuer une partition fractionnée rapide sur cette partition vide, je dois m'assurer que j'ai des statistiques sur la partition vide.

J'ai confirmé que le NUM_ROWS était 0 pour cette partition vide. Je n'ai donc pas eu à calculer les statistiques sur la partition. Ma première opération SPLIT PARTITION a été très rapide, quelques secondes seulement. La partition était vide et Oracle le savait. Ce qui m'a surpris, c'est que la nouvelle partition, USAGE_TRACKING_P201601 et USAGE_TRACKING_PMAX est passée aux valeurs NULL pour les statistiques. Cela signifiait que l'exécution de l'opération SPLIT PARTITION pour la deuxième nouvelle partition prendrait beaucoup de temps. Voici un exemple de ce que je veux dire. Tout d'abord, nous pouvons voir 0 lignes dans la partition de valeur maximale.

SQL> sélectionnez num_rows à partir de dba_tab_partitions
  2  où partition_name='USAGE_TRACKING_PMAX' ;
 
  NUM_ROWS
----------
         0

Maintenant, je vais diviser cette partition.

SQL> ALTER TABLE usage_tracking
  2  SPLIT PARTITION usage_tracking_pmax AT ( TO_DATE('02/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS') )
   3  INTO (PARTITION usage_tracking_p201601, PARTITION usage_tracking_pmax) ;
 
Tableau modifié.
Écoulé :00:00:03.13

Remarquez maintenant que les deux dernières partitions n'ont plus de statistiques.

SQL> sélectionnez num_rows à partir de dba_tab_partitions
  2  where partition_name='USAGE_TRACKING_PMAX' ;
 
  NUM_ROWS
----------
 
 
SQL> sélectionnez num_rows à partir de dba_tab_partitions
  2  où partition_name='USAGE_TRACKING_P201601' ;
 
  NUM_ROWS
----------
 
 

Sans statistiques, la prochaine partition fractionnée pour créer la partition de février 2016 prend beaucoup de temps.

SQL> ALTER TABLE nau_system.usage_tracking
  2  SPLIT PARTITION usage_tracking_pmax AT (TO_DATE('03/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS'))
  3  INTO (PARTITION usage_tracking_p201602, PARTITION usage_tracking_pmax) ;
 
Tableau modifié.
Écoulé :00:27:41.09

Comme le dit la note MOS, nous avons besoin des statistiques sur la partition pour effectuer une opération de fractionnement rapide. La solution consiste à calculer les statistiques sur la partition, puis à utiliser une commande ALTER TABLE pour créer toutes les partitions en même temps.

COMMENCER
 DBMS_STATS.gather_table_stats (tabname=>'USAGE_TRACKING',
 partname => 'USAGE_TRACKING_PMAX',
 granularité => 'PARTITION');
 FIN;
 /
ALTER TABLE usage_tracking
SPLIT PARTITION usage_tracking_pmax INTO
 (PARTITION usage_tracking_p201601 VALEURS INFÉRIEURES À (TO_DATE('02/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS')),
  PARTITION usage_tracking_p201602 VALEURS INFÉRIEURES À (TO_DATE('03/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS')),
  PARTITION usage_tracking_p201603 VALEURS INFÉRIEURES À (TO_DATE('04/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS')),
  PARTITION usage_tracking_p201604 VALEURS INFÉRIEURES À (TO_DATE('05/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS')),
  PARTITION usage_tracking_p201605 VALEURS INFÉRIEURES À (TO_DATE('06/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS')),
  PARTITION usage_tracking_p201606 VALEURS INFÉRIEURES À (TO_DATE('07/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS')),
  PARTITION usage_tracking_p201607 VALEURS INFÉRIEURES À (TO_DATE('08/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS')),
  PARTITION usage_tracking_p201608 VALEURS INFÉRIEURES À (TO_DATE('09/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS')),
  PARTITION usage_tracking_p201609 VALEURS INFÉRIEURES À (TO_DATE('10/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS') ),
  PARTITION usage_tracking_p201610 VALEURS INFÉRIEURES À (TO_DATE('11/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS') ),
  PARTITION usage_tracking_p201611 VALEURS INFÉRIEURES À (TO_DATE('12/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS') ),
  PARTITION usage_tracking_p201612 VALEURS INFÉRIEURES À (TO_DATE('01/01/2017 00:00:00','MM/DD/YYYY HH24:MI:SS') ),
  PARTITION usage_tracking_pmax);

Si j'avais laissé le script effectuer 12 opérations SPLIT PARTITION individuelles, j'aurais dû recalculer les statistiques sur la partition maximale entre chacune. L'utilisation d'une seule commande était plus efficace.