Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Schnelle Split-Partitionierung

Ich habe eine partitionierte Tabelle für einige Anwendungsprotokollierung. Vor ein paar Jahren habe ich die Tabelle mit einer Partition pro Monat partitioniert. Da wir uns dem Jahr 2016 nähern, ist es für mich an der Zeit, Partitionen für das neue Jahr hinzuzufügen. Die partitionierte Tabelle hat als letzte zwei Partitionen die Partition für Dezember 2015 und eine Partition, die MAXVALUE verwendet. Ich habe nie vor, Daten in der MAXVALUE-Partition zu haben. Es ist nur dazu da, SPLIT PARTITION-Operationen einfacher zu machen.

In der Vergangenheit habe ich Partitionen mit ähnlichen Befehlen wie den folgenden hinzugefügt:

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);

Die obigen SQL-Anweisungen teilen die MAXVALUE-Partition in zwei Partitionen auf. Es gibt 12 solcher Befehle, einen für jeden Monat.

Als ich dieses Jahr versuchte, das Skript für 2016 in einer Nicht-Produktionsumgebung auszuführen, stellte ich überrascht fest, dass die Ausführung dieser Befehle jeweils etwa 30 Minuten dauerte. In früheren Jahren waren sie in Sekunden fertig. Denken Sie daran, dass USAGE_TRACKING_PMAX leer ist, sodass keine Daten in eine geeignete Partition verschoben werden müssen.

Bei der Analyse der Aktivität meiner Sitzung, bei der SPLIT durchgeführt wurde, konnte ich deutlich db-Datei-Warteereignisse sehen, die zu dieser partitionierten Tabelle verfolgt wurden. Es war offensichtlich, dass die SPLIT-Operation die maximale Partition gelesen hat, obwohl sie leer war.

Die vergangenen Jahre haben gut funktioniert, aber diese Datenbank wurde kürzlich auf Oracle 12c aktualisiert. Ich habe Informationen zur Durchführung einer schnellen Partitionsaufteilung im MOS-Hinweis 1268714.1 gefunden, der besagt, dass dies für Oracle 10.2.0.3 und höher gilt, aber ich hatte keine Probleme in 11.2.0.4. Es war wahrscheinlich nur dummes Glück und ich habe keine 11g-Datenbank, um dies zu überprüfen, da alle meine aktualisiert wurden. Anstatt mich darauf zu konzentrieren, was sich geändert hat, werde ich mich daher einfach mit dem Problem befassen und mit meinem Tag weitermachen.

Laut MOS-Hinweis muss ich sicherstellen, dass ich Statistiken auf der leeren Partition habe, um eine schnelle Partitionsaufteilung auf dieser leeren Partition durchzuführen.

Ich habe bestätigt, dass NUM_ROWS für diese leere Partition 0 war. Ich musste also keine Statistiken auf der Partition berechnen. Meine erste SPLIT PARTITION-Operation war sehr schnell, nur wenige Sekunden. Die Partition war leer und Oracle wusste es. Was mich überraschte, war, dass die neue Partition, USAGE_TRACKING_P201601 und USAGE_TRACKING_PMAX für Statistiken auf NULL-Werte gingen. Dies bedeutete, dass die Durchführung des SPLIT PARTITION-Vorgangs für die zweite neue Partition lange dauern würde. Hier ist ein Beispiel dafür, was ich meine. Zuerst können wir 0 Zeilen in der Maximalwertpartition sehen.

SQL> select num_rows from dba_tab_partitions
  2  where partition_name='USAGE_TRACKING_PMAX';
 
  NUM_ROWS
----------
         0

Jetzt werde ich diese Partition aufteilen.

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);
 
Table altered.
Elapsed: 00:00:03.13

Beachten Sie nun, dass die letzten beiden Partitionen jetzt keine Statistiken mehr haben.

SQL> select num_rows from dba_tab_partitions
  2  where partition_name='USAGE_TRACKING_PMAX';
 
  NUM_ROWS
----------
 
 
SQL> select num_rows from dba_tab_partitions
  2  where partition_name='USAGE_TRACKING_P201601';
 
  NUM_ROWS
----------
 
 

Ohne Statistiken dauert es lange, bis die nächste geteilte Partition die Februar-2016-Partition erstellt.

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);
 
Table altered.
Elapsed: 00:27:41.09

Wie der MOS-Hinweis sagt, benötigen wir die Statistiken auf der Partition, um eine schnelle Teilungsoperation durchzuführen. Die Lösung besteht darin, Statistiken für die Partition zu berechnen und dann einen ALTER TABLE-Befehl zu verwenden, um alle Partitionen auf einmal zu erstellen.

BEGIN
 DBMS_STATS.gather_table_stats (tabname=>'USAGE_TRACKING',
 partname => 'USAGE_TRACKING_PMAX',
 granularity => 'PARTITION');
 END;
 /
ALTER TABLE usage_tracking
SPLIT PARTITION usage_tracking_pmax INTO
 (PARTITION usage_tracking_p201601 VALUES LESS THAN (TO_DATE('02/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS')),
  PARTITION usage_tracking_p201602 VALUES LESS THAN (TO_DATE('03/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS')),
  PARTITION usage_tracking_p201603 VALUES LESS THAN (TO_DATE('04/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS')),
  PARTITION usage_tracking_p201604 VALUES LESS THAN (TO_DATE('05/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS')),
  PARTITION usage_tracking_p201605 VALUES LESS THAN (TO_DATE('06/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS')),
  PARTITION usage_tracking_p201606 VALUES LESS THAN (TO_DATE('07/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS')),
  PARTITION usage_tracking_p201607 VALUES LESS THAN (TO_DATE('08/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS')),
  PARTITION usage_tracking_p201608 VALUES LESS THAN (TO_DATE('09/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS')),
  PARTITION usage_tracking_p201609 VALUES LESS THAN (TO_DATE('10/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS') ),
  PARTITION usage_tracking_p201610 VALUES LESS THAN (TO_DATE('11/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS') ),
  PARTITION usage_tracking_p201611 VALUES LESS THAN (TO_DATE('12/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS') ),
  PARTITION usage_tracking_p201612 VALUES LESS THAN (TO_DATE('01/01/2017 00:00:00','MM/DD/YYYY HH24:MI:SS') ),
  PARTITION usage_tracking_pmax);

Wenn ich das Skript verlassen hätte, um 12 einzelne SPLIT PARTITION-Operationen auszuführen, hätte ich die Statistiken für die maximale Partition zwischen jeder neu berechnen müssen. Die Verwendung eines Befehls war effizienter.