一部のアプリケーションログ用にパーティション化されたテーブルがあります。数年前、私は月に1つのパーティションでテーブルをパーティション化しました。 2016年が近づくにつれ、新年に向けてパーティションを追加する時期が来ました。パーティションテーブルには、最後の2つのパーティションとして、2015年12月のパーティションとMAXVALUEを使用するパーティションがあります。 MAXVALUEパーティションにデータを入れる予定はありません。 SPLITPARTITIONの操作を簡単にするためだけにあります。
以前は、次のようなコマンドでパーティションを追加していました。
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ステートメントは、MAXVALUEパーティションを2つのパーティションに分割します。そのようなコマンドは12あり、毎月1つです。
今年、非実稼働環境で2016年のスクリプトを実行しようとしたとき、これらのコマンドが完了するまでに約30分かかることに驚きました。以前は、数秒で完了しました。 USAGE_TRACKING_PMAXは空であるため、データを適切なパーティションに移動する必要はありません。
SPLITを実行しているセッションのアクティビティを分析すると、このパーティションテーブルに追跡されたdbファイル待機イベントを明確に確認できました。空であるにもかかわらず、SPLIT操作が最大パーティションを読み取っていることは明らかでした。
以前は問題なく機能していましたが、このデータベースは最近Oracle12cにアップグレードされました。高速分割パーティション操作を実行する方法に関する情報をMOSNote1268714.1で見つけました。これは、Oracle 10.2.0.3以降に適用されると書かれていますが、11.2.0.4では問題はありませんでした。それはおそらく運が悪かっただけで、私のすべてがアップグレードされたので、これをチェックするための11gデータベースがありません。そのため、何が変わったかに焦点を当てるのではなく、問題に対処して1日を続けます。
MOSのメモによると、この空のパーティションで高速分割パーティションを実行するには、空のパーティションに統計があることを確認する必要があります。
この空のパーティションのNUM_ROWSが0であることを確認しました。そのため、パーティションの統計を計算する必要はありませんでした。私の最初のSPLITPARTITION操作は非常に速く、ほんの数秒でした。パーティションは空であり、Oracleはそれを認識していました。私が驚いたのは、新しいパーティションUSAGE_TRACKING_P201601とUSAGE_TRACKING_PMAXが統計のためにNULL値になったことです。これは、2番目の新しいパーティションに対してSPLITPARTITION操作を実行するのに長い時間がかかることを意味しました。これが私の言いたいことの例です。まず、最大値パーティションに0行が表示されます。
SQL> select num_rows from dba_tab_partitions
2 where partition_name='USAGE_TRACKING_PMAX';
NUM_ROWS
----------
0
次に、そのパーティションを分割します。
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
最後の2つのパーティションに統計がないことに注意してください。
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
----------
統計がない場合、2016年2月のパーティションを作成するための次の分割パーティションには長い時間がかかります。
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
MOSノートに記載されているように、高速分割操作を実行するには、パーティションの統計が必要です。解決策は、パーティションの統計を計算してから、1つのALTERTABLEコマンドを使用してすべてのパーティションを一度に作成することです。
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);
スクリプトを12個の個別のSPLITPARTITION操作の実行に任せた場合、各操作間の最大パーティションの統計を再計算する必要があります。 1つのコマンドを使用する方が効率的でした。