sql >> Database teknologi >  >> RDS >> Oracle

Hurtig opdeling af partitionering

Jeg har en partitioneret tabel til noget applikationslogning. For et par år siden opdelte jeg bordet med en partition om måneden. Da vi nærmer os 2016, er det tid for mig at tilføje partitioner til det nye år. Den partitionerede tabel har, som dens sidste to partitioner, partitionen for december 2015 og en partition, der bruger MAXVALUE. Jeg har aldrig planer om at have nogen data i MAXVALUE-partitionen. Den er kun til for at gøre SPLIT PARTITION-operationer nemmere.

Tidligere ville jeg tilføje partitioner med kommandoer svarende til følgende:

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

SQL-sætningerne ovenfor vil opdele MAXVALUE-partitionen i to partitioner. Der er 12 sådanne kommandoer, en for hver måned.

I år, da jeg prøvede at køre scriptet for 2016 i et ikke-produktionsmiljø, var jeg overrasket over at finde ud af, at disse kommandoer tog omkring 30 minutter for hver af dem at fuldføre. I tidligere år gennemførte de på få sekunder. Husk, at USAGE_TRACKING_PMAX er tom, så ingen data skal flyttes til en passende partition.

Ved at analysere aktiviteten af ​​min session, der udfører SPLIT, kunne jeg tydeligt se db-fil ventehændelser, som blev sporet til denne opdelte tabel. Det var tydeligt, at SPLIT-operationen læste max-partitionen, selvom den var tom.

Tidligere år fungerede fint, men denne database blev for nylig opgraderet til Oracle 12c. Jeg fandt information om, hvordan man udfører en hurtig delt partitionsoperation i MOS Note 1268714.1, som siger, at dette gælder for Oracle 10.2.0.3 og nyere, men jeg havde ingen problemer i 11.2.0.4. Det var nok bare et dumt held, og jeg har ikke en 11g database at tjekke dette ud på, da alle mine er blevet opgraderet. Som sådan vil jeg i stedet for at fokusere på det, der har ændret sig, bare tage fat på problemet og komme videre med min dag.

I henhold til MOS-notatet skal jeg sørge for, at jeg har statistik på den tomme partition for at udføre en hurtig opdelt partition på denne tomme partition.

Jeg bekræftede, at NUM_ROWS var 0 for denne tomme partition. Så jeg behøvede ikke at beregne statistik på partitionen. Min første SPLIT PARTITION operation var meget hurtig, kun et par sekunder. Partitionen var tom, og Oracle vidste det. Det, der overraskede mig, var, at den nye partition, USAGE_TRACKING_P201601 og USAGE_TRACKING_PMAX gik til NULL-værdier for statistik. Dette betød, at det ville tage lang tid at udføre SPLIT PARTITION-operationen for den anden nye partition. Her er et eksempel på hvad jeg mener. For det første kan vi se 0 rækker i partitionen med maksimal værdi.

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

Nu vil jeg opdele den 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);
 
Table altered.
Elapsed: 00:00:03.13

Bemærk nu, at de sidste to partitioner nu ikke har nogen statistik.

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

Uden statistik tager den næste opdelte partition for at oprette februar 2016-partitionen lang tid.

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

Som MOS-notatet siger, har vi brug for statistikken på partitionen for at udføre en hurtig splitoperation. Løsningen er at beregne statistik på partitionen og derefter bruge én ALTER TABLE-kommando til at oprette alle partitionerne på én gang.

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

Hvis jeg ville have overladt scriptet til at udføre 12 individuelle SPLIT PARTITION-operationer, så ville jeg have været nødt til at genberegne statistik på den maksimale partition mellem hver enkelt. Det var mere effektivt at bruge én kommando.


  1. Mapping array med Hibernate

  2. Find ud af, om værdien er nummer i MySQL

  3. MySQL ENUM type vs join tabeller

  4. Næsten nul nedetid automatiserede opgraderinger af PostgreSQL-klynger i skyen (del I)