Segment Partitioning

目次

大容量のデータを効率的に管理するための手法として、セグメント分割(Segment Partitioning)が普遍的に活用されます。Oracleは、範囲パーティショニング(Range Partitioning)、ハッシュ・パーティショニング(Hash Partitioning)、リスト・パーティショニング(List Partitioning)、複合パーティショニング(Composite Partitioning)など現存するDBMSの中で最も多様なパーティショニング技法を提供します。セグメント分割を使用する理由は、管理の利便性と性能の二つに要約することができます。

管理の利便

パーティショニングは、大容量のデータを効率的に分割して管理することができる方法を提供します。時間による範囲パーティショニングが代表的な例とすることができます。データを時間単位で定期的に整理する作業を行う場合、実質的にパーティショニングを使用することだけが唯一の解決策だと見ることができるのです。Oracleは、パーティショニング作業に必要なほとんどの作業をオンラインで実行することができる機能を提供します。オンラインオプションのパーティショニング作業を使用すると、DDLによるシステム停止をせずにデータのクリーンアップ操作を実行することができます。

性能

パーティショニングがパフォーマンスにプラスの影響を与えることの一般的な期待とは異なり、OLTP環境では、パーティショニングとアプリケーションのパフォーマンスは、大きな相関関係がないと見てもよいと考えられます。 OLTP環境で実行されているほとんどの作業は、インデックスを経由した小さいサイズのLogical Readsを必要とするため、パーティショニングの利点が大きくありません。しかし、パーティショニングによる、期待されるブロックの分散効果により、OLTPシステムでも肯定的な性能効果をもたらす場合もあります。 一方、DSS環境では、パーティショニングがパフォーマンスに与える影響が非常に大きいと言えます。まず、パーティションプルーニング(Partition Pruning)を介してテーブル全体のスキャンを実行せずに、必要な特定の範囲のパーティションのスキャンだけを実行することができます。次の実行計画は、パーティションプルーニングが発生した場合の簡単な例として、FTSを実行しても、テーブル全体をスキャンせずに一つのパーティションだけをスキャンすることを確認することができます。

SELECT STATEMENT ALL_ROWS-Cost : 25
  PARTITION RANGE SINGLE  
   TABLE ACCESS FULL OWI.PART_TEST(1)

DMLは複数のパーティションに分かれていて、DMLの性能を極大化することがあります。DMLの性能のディスク競合(ディスク競合)を検討する必要があります。DMLの並列処理を円滑に行うために、DMLの性能を向上させる方法を提供します。然しながら、DMLの動作は致命的であると言えます。別のパーティションを守るためにディスクを配置することは不可能です。各パーティションは構成を提供するブロックを多数持ち、並列プロセスを構築します。

DMLの更新DMLを有効にすると、更新、削除が行えます。 DMLを並列化するDMLを実行すると、DMLを並列化することはできません。

- ケース1:DMLを並列化
SQL> ALTER SESSION DISABLE PARALLEL DML; デフォルトはDISABLE状態です
SQL> UPDATE / * + PARALLEL(PART_TEST)* /
PART_TEST
SET ID = ID;
行の行ソース操作
----- --------------------------------------------- ------
      0 UPDATE PART_TEST(cr = 18 pr = 0 pw = 0 time = 179908 us)
     30 PXコーディネーター(cr = 18 pr = 0 pw = 0 time = 169813 us)
      0 PX SEND QC(ランダム):TQ10000(cr = 0 pr = 0 pw = 0 time = 0 us)
      0 PX BLOCK ITERATOR PARTITION:1 3(cr = 0 pr = 0 pw = 0 time = 0 us)
      0テーブルアクセスFULL PART_TEST PARTITION:1 3(cr = 0 pr = 0 pw = 0 time = 0 us)

上の実行計画を詳しく見ればテーブルをスキャンする作業だけが並列で実行されて、実際のUPDATE文は並列で実行されないことを確認することができます。 反面セッション レベルで並列DMLを活性化した場合にはUPDATE作業自体が並列で実行されます。

- ケース2:DMLを並列化
SQL> ALTER SESSIONはPARALLEL DMLを有効にします。
SQL> UPDATE / * + PARALLEL(PART_TEST)* /
PART_TEST
SET ID = ID;
行の行ソース操作
-------- ------------------------------------------ ---------
          4 PXコーディネーター(cr = 36 pr = 0 pw = 0 time = 677646 us)
          0 PX SEND QC(ランダム):TQ10000(cr = 0 pr = 0 pw = 0 time = 0 us)
          0 UPDATE PART_TEST(cr = 0 pr = 0 pw = 0 time = 0 us)
          0 PX BLOCK ITERATOR PARTITION:1 3(cr = 0 pr = 0 pw = 0 time = 0 us)
          0テーブルアクセスFULL PART_TEST PARTITION:1 3(cr = 0 pr = 0 pw = 0 time = 0

上記の実行計画は、前の実行計画とは異なり、UPDATEステートメント自体が並列に実行され、パーティション単位で並列化が行われることを確認することができます。

2つのパーティションテーブル、あるいは一つのパーティションテーブルと通常のテーブルを結合する場合、Oracleは可能なパーティション指向結合(Partition-wise Join)を実行します。パーティション指向結合は、1つの結合操作をパーティションに基づいて区分された複数の小さな結合に分離して並列的に結合を実行する作業を言います。大量のデータを結合して、結果を抽出する場合には、パーティション指向の結合を利用することで、パフォーマンスを最大化することができます。この場合にも、パラレルDMLと同様に、ディスクの競合を最小限に抑えることが性能面で有利となります。パーティション指向結合で注意すべき点は、最大DOPがパーティションの数によって制限されるということです。パーティション指向の結合は、異なるパーティションテーブルを各パーティション単位で結合する作業であるため、可能な限り同時に実行することができる並列プロセスの数は、パーティションの数を超えることができません。結局、パーティション単位の作業分割が有利であることを、可能な限り多くのCPUを使用して作業することが有利かどうかのテストを介して判断するしかないのです。

ハッシュパーティショニングの意味

Oracleが提供するパーティショニング手法のハッシュ・パーティショニング(Hash Partitioning)は、パーティション・キーのハッシュ値に基づいてパーティションを割り当てる機能を提供します。範囲パーティショニングやリストパーティショニングのように値の範囲に基づいてデータを分散保存する役割をする他のパーティショニング技法とは異なり、ハッシュパーティションは、ハッシュ値に基づいてランダムにパーティションを割り当てるため、大量のデータを効率的に管理する目的には会いません。一方、ランダムな分散がもたらすブロック分散の効果を利用して、ブロックレベルの競合を減らす目的では活用可能です。次の例は、ブロックの競合によってbuffer busy waits待機イベントが広範囲に発生するテーブルをハッシュパーティショニングを利用して強制的に分散させた場合にbuffer busy waits待機イベントがどのよう減るかを示しています。

- Case 1:パーティショニングを適用していないテーブルに対して10個のセッションが
         同時にUPDATEを実行する場合、buffer busy waits待機イベントが広範囲に
         発生することを確認することができます。
CREATE TABLE t_buffer_busy_waits
 (
  id NUMBER、
  name VARCHAR2(10)
 )
************************************************** ***************************
UPDATE T_BUFFER_BUSY_WAITS SET NAME = 'name' ||:B1
WHERE
 ID = 10 *(:B2 -1)+:B1

call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- --------- - ---------- --------
Parse 1 0.00 0.00 0 0 0 0
Execute 8000 3.01 25.57 0 373741 23516 8000
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- --------- ------- ------- ------ ---- -------
total 8001 3.01 25.58 0 373741 23516 8000

Misses in library cache during parse:1
Misses in library cache during execute:1
Optimizer mode:CHOOSE
Parsing user id:63(recursive depth:2)

Elapsed times include waiting on following events:
  Event waited on Times Max。 Wait Total Waited
  ------------------------------------- Waited ---------- - ----------
  buffer busy waits 843 1.00 14.29
  latch:In memory undo latch 97 0.07 0.46
  latch:cache buffers chains 127 0.10 1.09
  latch free 4 0.04 0.04
  latch:cache buffers lru chain 2 0.00 0.00
  log file switch completion 3 0.99 1.00
  log file switch(checkpoint incomplete)3 1.00 2.09
  latch:undo global data 6 0.01 0.01
  enq:HW - contention 1 0.00 0.00
  latch:library cache 1 0.00 0.00
************************************************** ***************************

- Case 2:100個のパーティションにハッシュ・パーティショニングを適用した後、
      同じ負荷でUPDATEを実行した場合buffer busy waits待機イベントが
      大きく減少することが確認できます。
      これはハッシュ・パーティショニングによってブロックが分散された
      効果が現れたものです。
CREATE TABLE t_buffer_busy_waits
 (
  id NUMBER、
  name VARCHAR2(10)
 )
 PARTITION BY HASH(id)PARTITIONS 100;
************************************************** ****************************

上記のテストの結果を見ると、ハッシュ・パーティショニングを使用してブロックを分散させた場合、buffer busy waits待機が14.29秒で1.18秒大きく減少したことを確認することができます。

RACシステムでは、パーティショニングによるブロック分散効果は、シングルインスタンス環境でより大きな意味を持ちます。RACシステムでのホット・ブロックは、ローカルバッファロック競合だけでなく、グローバルバッファロック(BLロック)競合を誘発し、ノード間のブロックの最新バージョンを常に送信する必要があるため、相互接続に多くの負荷を誘発します。この場合、各プロセスは、gc buffer busyイベントやgc current requestイベントとそれに対応するFixed-upイベントで、gc current block busy、gc current grant busy、gc current block2/3-way類のイベントを待機することになります。

ハッシュ・パーティショニングの適用方法

実際の業務でパーティショニングを適用してみた経験がある読者であれば、ハッシュ・パーティショニングの実用性について多くの疑問を持っていることでしょう。大容量のデータ管理のためなら範囲パーティショニングやリストパーティショニングでは、ほとんどの処理することができますので、ハッシュ・パーティショニングを適用する理由を見つけるのは難しいからです。しかし、高い同時実行を持つシングルインスタンス環境やRAC環境では、ハッシュ・パーティショニングがもたらすブロック分散効果を、パフォーマンスの向上を期待することができます。問題は、ブロックがランダムに分散されてしまうハッシュ・パーティショニング固有の特徴により、実際の業務で適用するのが不可能な場合が多いということなのです。このような悩みは、複合パーティショニングを適用することにより、解決することができます。複合パーティショニングとは、パーティションごとに再びサブパーティショニングを適用する手法を言います。次の例のように、範囲パーティショニングとハッシュ・パーティショニングを利用して複合パーティショニングを適用することができます。

CREATE TABLE PART_TEST(ID NUMBER,NAME VARCHAR2(100))
PARTITION BY RANGE(ID)
SUBPARTITION BY HASH(NAME)
SUBPARTITION TEMPLATE
(
    SUBPARTITION SUBPART1,
    SUBPARTITION SUBPART2,
    SUBPARTITION SUBPART3,
    SUBPARTITION SUBPART4
)
(
    PARTITION PART1 VALUES LESS THAN(10),
    PARTITION PART2 VALUES LESS THAN(20),
    PARTITION PART3 VALUES LESS THAN(30)
);
SELECT TABLE_NAME, PARTITION_NAME, SUBPARTITION_NAME
FROM DBA_TAB_SUBPARTITIONS WHERE TABLE_NAME = 'PART_TEST';
TABLE_NAME		PARTITION_NAME	SUBPARTITION_NAME
----------		-------------	-------------------
PART_TEST		PART1		PART1_SUBPART1
PART_TEST		PART1		PART1_SUBPART2
PART_TEST		PART1		PART1_SUBPART3
PART_TEST		PART1		PART1_SUBPART4
PART_TEST		PART2		PART2_SUBPART1
PART_TEST		PART2		PART2_SUBPART2
PART_TEST		PART2		PART2_SUBPART3
PART_TEST		PART2		PART2_SUBPART4
PART_TEST		PART3		PART3_SUBPART1
PART_TEST		PART3		PART3_SUBPART2
PART_TEST		PART3		PART3_SUBPART3
PART_TEST		PART3		PART3_SUBPART4

もう一度まとめると、大容量のテーブルで発生するホット・ブロック現象を、ブロック分散を使用して解決しようとする場合には、まず範囲/リストパーティショニングを使用して全体のレベルのパーティションを構成して、ハッシュ・パーティショニングを使用してサブパーティションを構成することにより、データ管理の使いやすさという本来の目的とブロック分散というパフォーマンスの改善の目的をすべて達成することができます。

パーティショニングとディスクI / Oの分散

特定のディスクへのI/O操作が集中する場合は、ホットスポット(Hot Spot)現象が発生します。特定のディスクがホットスポットになる場合には、I/O待機時間が大幅に増加して、これにより、I/O操作のパフォーマンスが大幅に低下します。最悪の場合、Oracleが単一のブロックを読み込むのに数秒〜数十秒程度の時間がかかるほどの性能低下現象を経験することになるのです。

ホットスポット現象を解消する唯一の方法は、特定のディスクへのI/O操作が集まる現象を除去することになります。これは、アプリケーションの変更やチューニングでは達成することができず、ディスクレベルのチューニングだけで解決することができるのです。最良の方法は、Oracleで使用するデータファイルを可能な限り多くのディスクにストライプすることになります。LVM(Logical Volume Manager)を使用している場合は、1つのLogical Volumeに多くの数のディスクを割り当て、Logical Volumeレベルでのストライピングを実行すると、されています。一つのデータファイルが複数のディスクにストライプされた場合、特定のディスクへのI/O操作が集まる現象が自然に解消されます。もしLVMを使用していないか、またはでデバイスの使用によってLVMレベルのストライピングを適用するのは難しい状況だとすると、セグメントレベルのパーティショニングを使用して同様の効果を出すことができます。例えば1つのセグメントを範囲+ハッシュ複合パーティションで構成した場合、各パーティションごとに最大限の独立したディスクを割り当てることができます。これにより、1つのセグメントが多数のディスクに自然に分散される。自然、特定のディスクがホットスポットに変わる現象を防止することができるのです。

ディスク レベルで発生する競合現象はディスクの配置方法を全面的に修正してこそ解決が可能なので、可能なシステム設計および構築段階で多様な検討とテストを通じて最適なシステムを性能を保証されるように考慮しなければなりません。構築が完了して運営に入ったシステムのディスク配置を修正することが現実的にほとんど不可能な場合が多いためです。