4 シャーディング方法

この章では、Oracle Shardingでサポートされるシャーディング方法、方法の選択およびサブパーティションの使用方法について説明します。

次の項目では、Oracle Shardingでサポートされるシャーディング方法について説明します。

システム管理のシャーディング

システム管理のシャーディングでは、シャードへのデータのマッピングをユーザーが指定する必要はありません。コンシステント・ハッシュによるパーティション化を使用して、データが自動的にシャード間に分散されます。パーティション化アルゴリズムにより、データがシャード間に均一およびランダムに分散されます。

システム管理のシャーディングで使用される分散はホット・スポットを回避し、シャード間で均一なパフォーマンスを実現するためのものです。Oracle Shardingは、SDBへのシャードの追加または削除の際に、バランスの取れたチャンク分散を自動的に維持します。

コンシステント・ハッシュはスケーラブルな分散システムでよく使用されるパーティション化の方法です。従来のハッシュ・パーティション化とは異なります。従来のハッシュの場合はバケット数がHF(key) % Nとして計算されます。ここで、HFはハッシュ関数、Nはバケット数です。この方法はNが一定の場合はうまく機能しますが、Nが変化するとすべてのデータの再シャッフルが必要になります。

線形ハッシュ法などのより高度なアルゴリズムの場合、ハッシュ・バケットを追加するために表全体を再ハッシュする必要はありませんが、バケット数が2のべき乗のみ、およびバケットを分割できるオーダーのみなど、バケット数に制限があります。

Oracle Shardingで使用するコンシステント・ハッシュの実装では、このような制限を回避するために、次の図のように、ハッシュ関数の値の取りうる範囲(たとえば、0から232)をN個の隣接する間隔のセットに分割し、それぞれの間隔をチャンクに割り当てます。この例では、SDBに1024個のチャンクが含まれ、各チャンクに222のハッシュ値の範囲が割り当てられます。したがって、コンシステント・ハッシュによるパーティション化は、本質的にはハッシュ値の範囲によるパーティション化です。

図4-1 チャンクに割り当てられるハッシュ値の範囲

図4-1の説明が続きます
「図4-1 チャンクに割り当てられるハッシュ値の範囲」の説明

すべてのシャードの計算能力が同じだとすると、SDBの各シャードに等しい数のチャンクが割り当てられます。たとえば、16個のシャードを含むSDB内に1024個のチャンクが作成されると、各シャードに64個のチャンクが含まれます。

SDBへのシャードの追加や削除の際の再シャーディングの場合、いくつかのチャンクがシャード間を移動して、シャード間のチャンクの均一な分散が維持されます。このプロセスでチャンクの内容は変化せず、再ハッシュは行われません。

1つのチャンクが分割されるときに、ハッシュ値の範囲が2つの範囲に分割されますが、他のチャンクに対して何かを行う必要はありません。任意のチャンクをいつでも個別に分割できます。

接続リクエストのシャードへの送信にかかわるSDBのすべてのコンポーネントに、各シャードでホストされるチャンクのリスト、および各チャンクに関連付けられたハッシュ値の範囲を含むルーティング表が保持されます。特定のデータベース・リクエストのルーティング先を決定するために、ルーティング・アルゴリズムによって、シャーディング・キーで指定された値にハッシュ関数が適用され、計算されたハッシュ値が適切なチャンクにマップされ、次にチャンクを含むシャードにマップされます。

システム管理のシャーディングのSDB内のチャンク数は、CREATE SHARDCATALOGコマンドで指定できます。指定しない場合は、デフォルト値としてシャード当たり120個のチャンクが使用されます。SDBのデプロイ後にチャンク数を変更する方法はチャンクの分割のみです。

コンシステント・ハッシュによってパーティション化されたシャード表を作成する前に、表のパーティションを格納するために表領域のセット(チャンク当たり1つの表領域)を作成する必要があります。表領域はCREATE TABLESPACE SETのSQL文を実行すると自動的に作成します。

表領域セットのすべての表領域が同じ物理属性を持ち、Oracle Managed Files (OMF)のみを格納できます。最も簡単な形式の場合、CREATE TABLESPACE SET文は、たとえば次のように表領域セットの名前という1つのパラメータのみを持ちます。

CREATE TABLESPACE SET ts1;

この場合、セットの各表領域にデフォルトの属性を持つ1つのOMFファイルが含まれます。表領域の属性をカスタマイズするには、文にUSING TEMPLATE句(次の例を参照)を追加します。USING TEMPLATE句は、セットの各表領域に適用される属性を指定します。

CREATE TABLESPACE SET ts1
USING TEMPLATE
( 
 DATAFILE SIZE 10M
 EXTENT MANAGEMENT LOCAL UNIFORM SIZE 256K
 SEGMENT SPACE MANAGEMENT AUTO
 ONLINE
)
;

表領域セットが作成されたら、コンシステント・ハッシュでパーティション化される表を作成して、セットに属する表領域にパーティションを格納できます。CREATE TABLE文は、たとえば次のようになります。

CREATE SHARDED TABLE customers 
( cust_id     NUMBER NOT NULL
, name        VARCHAR2(50)
, address     VARCHAR2(250) 
, location_id VARCHAR2(20)
, class       VARCHAR2(3)
, signup      DATE
, CONSTRAINT cust_pk PRIMARY KEY(cust_id)
)
PARTITION BY CONSISTENT HASH (cust_id)
PARTITIONS AUTO
TABLESPACE SET ts1
;

この文のPARTITIONS AUTOは、パーティション数が自動的に表領域セットts1の表領域の数(チャンク数と等しい)に設定され、各パーティションが個別の表領域に格納されることを意味します。

表領域セットの各表領域が別個のチャンクに属します。つまり、1つのチャンクは所定の表領域セットの1つの表領域のみを含むことができます。ただし、同じ表ファミリに属する複数の表に同じ表領域セットを使用できます。この場合、セットの各表領域に複数のパーティション(各表から1つ)が格納されます。

または、表ファミリの各表を個別の表領域セットに格納できます。この場合、1つのチャンクに複数の表領域(各表領域セットから1つ)が含まれ、各表領域に1つのパーティションが格納されます。

次の図は、単一シャード表のユースケースの場合のパーティション、表領域およびシャード間の関係を示しています。この場合、各チャンクに1つの表領域が含まれ、各表領域に1つのパーティションが格納されます。

図4-2 システム管理のシャーディング

図4-2の説明が続きます
「図4-2 システム管理のシャーディング」の説明

ノート:

シャーディング方法はGDSCTL CREATE SHARDCATALOGコマンドで指定し、後から変更することはできません。

ユーザー定義のシャーディング

ユーザー定義のシャーディングでは、個々のシャードへのデータのマッピングをユーザーが明示的に指定できます。これは、パフォーマンスや規制などの理由で、特定のデータを特定のシャードに格納する必要があり、管理者がシャード間のデータの移動を完全に制御する必要がある場合に使用します。

レプリケーション方法としてOracle GoldenGateが使用されている場合、ユーザー定義のシャーディングはサポートされません。

ユーザー定義のシャーディングのもう1つのメリットとして、シャードの計画停止または計画外停止の場合に、どのデータが使用できないかをユーザーが正確に知ることができます。ユーザー定義のシャーディングのデメリットは、データベース管理者が、シャード間のデータおよびワークロードの分散のバランスを監視して維持する必要があることです。

ユーザー定義のシャーディングの場合、範囲またはリストによってシャード表をパーティション化できます。シャード表のCREATE TABLE構文は、各パーティションを個別の表領域に格納する必要があることを除き、通常の表のための構文とそれほど違いはありません。

 CREATE SHARDED TABLE accounts
( id             NUMBER
, account_number NUMBER
, customer_id    NUMBER
, branch_id      NUMBER
, state          VARCHAR(2) NOT NULL
, status         VARCHAR2(1)
)
PARTITION BY LIST (state)
( PARTITION p_northwest VALUES ('OR', 'WA') TABLESPACE ts1
, PARTITION p_southwest VALUES ('AZ', 'UT', 'NM') TABLESPACE ts2
, PARTITION p_northcentral VALUES ('SD', 'WI') TABLESPACE ts3
, PARTITION p_southcentral VALUES ('OK', 'TX') TABLESPACE ts4
, PARTITION p_northeast VALUES ('NY', 'VM', 'NJ') TABLESPACE ts5
, PARTITION p_southeast VALUES ('FL', 'GA') TABLESPACE ts6
)
;

ユーザー定義のシャーディングには表領域セットはありません。各表領域を個別に作成し、シャード領域と明示的に関連付ける必要があります。シャード領域はシャードのセットで、キーの値の範囲またはリストに対応するデータが格納されます。

ユーザー定義のシャーディングでは、シャード領域が1つのシャード、または完全にレプリケートされたシャードのセットから構成されます。ユーザー定義のシャーディングでのレプリケーションの詳細は、シャード・レベルの高可用性を参照してください。わかりやすいように、各シャード領域が1つのシャードから構成されると仮定します。

次の構文を使用して、前述の例に示したaccounts表の表領域を作成します。

CREATE TABLESPACE tbs1 IN SHARDSPACE west;
CREATE TABLESPACE tbs2 IN SHARDSPACE west;

CREATE TABLESPACE tbs3 IN SHARDSPACE central;
CREATE TABLESPACE tbs4 IN SHARDSPACE central;

CREATE TABLESPACE tbs5 IN SHARDSPACE east;
CREATE TABLESPACE tbs6 IN SHARDSPACE east;

CREATE TABLESPACE文を実行する前に、次のGDSCTLコマンドを使用してシャード領域を作成し、シャードを移入する必要があります。

ADD SHARDSPACE –SHARDSPACE west, central, east;
ADD SHARD –CONNECT shard-1 –SHARDSPACE west;
ADD SHARD –CONNECT shard-2 –SHARDSPACE central;
ADD SHARD –CONNECT shard-3 –SHARDSPACE east;

次の図は、前述の例に示したaccounts表について、表領域へのパーティションのマッピング、およびシャードへの表領域のマッピングを示しています。

図4-3 ユーザー定義のシャーディング

図4-3の説明が続きます
「図4-3 ユーザー定義のシャーディング」の説明

システム管理のシャーディングと同様に、ユーザー定義のシャーディングで作成される表領域もチャンクに割り当てられます。ただし、SDBにシャードを追加したときに、チャンクの移行は自動的には開始しません。移行する必要がある各チャンクに対して、ユーザーがMOVE CHUNKコマンドを実行する必要があります。

SPLIT CHUNKコマンドはシステム管理のシャーディングでは、ハッシュ範囲の中央でチャンクを分割するために使用されますが、ユーザー定義のシャーディングではサポートされません。ALTER TABLE SPLIT PARTITION文を使用してチャンクを分割する必要があります。

ノート:

シャーディング方法はGDSCTL CREATE SHARDCATALOGコマンドで指定し、後から変更することはできません。

ユーザー定義のシャード・データベースでは、Oracle Data GuardとOracle Active Data Guardの2つのレプリケーション・スキーマがサポートされます。

コンポジット・シャーディング

コンポジット・シャーディング方法では、コンシステント・ハッシュによりパーティション化された表のデータの異なるサブセットについて、複数のシャード領域を作成できます。シャード領域はシャードのセットで、キーの値の範囲またはリストに対応するデータが格納されます。

システム管理のシャーディングでは、コンシステント・ハッシュによるパーティション化を使用して、シャード間にデータをランダムに分散します。これは、範囲またはリストによるパーティション化を使用するユーザー定義のシャーディングと比べて、よりよいロード・バランスを実現します。ただし、システム管理のシャーディングでは、データのシャードへの割当てをユーザーが制御できません。

主キーのコンシステント・ハッシュによるシャーディングの際には、データのサブセットを異なる地理的場所に格納する、データのサブセットに異なるハードウェア・リソースを割り当てる、または高可用性と障害回復を異なる構成にするために、SDB内のデータのサブセットを区別する必要が生じることがよくあります。通常は、この区別は顧客の場所やサービスのクラスなど、別の(主キーでない)列の値に基づいて行われます。

コンポジット・シャーディングは、ユーザー定義のシャーディングとシステム管理のシャーディングの組合せで、必要に応じて両方の利点を活用できます。コンポジット・シャーディングでは、最初にデータがリストまたは範囲により複数のシャード領域にパーティション化され、次にコンシステント・ハッシュにより各シャード領域の複数のシャード間にさらにパーティション化されます。

2つのレベルのシャーディングにより、各シャード領域のシャード間のバランスのとれたデータ分散を自動的に維持し、同時にシャード領域間にデータをパーティション化できます。

たとえば、高速なサーバーでホストされる3つのシャードをゴールド顧客に割り当て、低速のマシンでホストされる4つのシャードをシルバー顧客に割り当てるとします。顧客IDのコンシステント・ハッシュによるパーティション化を使用して、シャードの各セット内に顧客を分散する必要があります。

図4-4 コンポジット・シャーディング

図4-4の説明が続きます
「図4-4 コンポジット・シャーディング」の説明

このような構成では、次のGDSCTLコマンドを使用して2つのシャード領域を作成する必要があります。

ADD SHARDSPACE –SHARDSPACE shspace1;
ADD SHARDSPACE –SHARDSPACE shspace2;

ADD SHARD –CONNECT shard1 –SHARDSPACE shspace1;
ADD SHARD –CONNECT shard2 –SHARDSPACE shspace1;
ADD SHARD –CONNECT shard3 –SHARDSPACE shspace1;

ADD SHARD –CONNECT shard4 –SHARDSPACE shspace2;
ADD SHARD –CONNECT shard5 –SHARDSPACE shspace2;
ADD SHARD –CONNECT shard6 –SHARDSPACE shspace2;
ADD SHARD –CONNECT shard7 –SHARDSPACE shspace2;

コンポジット・シャーディングでは、他のシャーディング方法と同様に、表領域を使用してシャードへのパーティションのマッピングを指定します。シャード表のデータのサブセットを異なるシャード領域に割り当てるために、次の例に示すように、各シャード領域に個別の表領域のセットを作成する必要があります。

CREATE TABLESPACE SET tbs1 IN SHARDSPACE shspace1;
CREATE TABLESPACE SET tbs2 IN SHARDSPACE shspace2;

ユーザー定義のデータのサブセットを異なる表領域に格納するために、Oracle Shardingには、パーティションをセットにグループ化し、パーティションの各セットを表領域のセットと関連付ける構文が用意されています。パーティション・セットのサポートは、論理的には、コンシステント・ハッシュによるパーティション化の上位に実装される高レベルのパーティション化に相当すると考えることができます。

次の例に示す文では、サービスのクラスに基づいて、シャード表をgoldとsilverという2つのパーティション・セットにパーティション化しています。各パーティション・セットが個別の表領域に格納されます。次に、各パーティション・セットのデータが、顧客IDのコンシステント・ハッシュによってさらにパーティション化されます。

CREATE SHARDED TABLE customers
( cust_id NUMBER NOT NULL
, name VARCHAR2(50)
, address VARCHAR2(250) 
, location_id VARCHAR2(20) 
, class VARCHAR2(3) 
, signup_date DATE 
, CONSTRAINT cust_pk PRIMARY KEY(cust_id, class) 
)
PARTITIONSET BY LIST (class) 
  PARTITION BY CONSISTENT HASH (cust_id)
  PARTITIONS AUTO
(PARTITIONSET gold VALUES (‘gld’) TABLESPACE SET tbs1,
 PARTITIONSET silver VALUES (‘slv’) TABLESPACE SET tbs2)
;

ノート:

Oracle Database 12cリリース2では、表の単一のパーティション・セットのみをシャード領域に格納できます。

シャーディング方法はGDSCTL CREATE SHARDCATALOGコマンドで指定し、後から変更することはできません。

サブパーティション化とシャーディングの使用

Oracle Shardingは表のパーティション化に基づくため、Oracle Databaseで提供されるすべてのサブパーティション方法がシャーディングでもサポートされます。

サブパーティション化は各パーティションをさらに小さい部分に分割します。これはシャード内の効率的なパラレル実行、特に、シャード当たりのパーティション数が少ないときの範囲またはリストによるシャーディングの場合に役立つ可能性があります。

管理性の面では、サブパーティションを個別の表領域に割り当てて記憶域階層間で移動することで、サブパーティション化によって記憶域の階層化をサポートできます。シャーディングのスケーラビリティと可用性という利点を損なわず、パーティション・プルーニングと主キーによるパーティション単位の結合の実行を犠牲にすることなく、記憶域階層間でサブパーティションを移行できます。

次の例は、コンシステント・ハッシュと範囲によるサブパーティション化を組み合せたシステム管理のシャーディングを示しています。

CREATE SHARDED TABLE customers 
( cust_id     NUMBER NOT NULL
, name        VARCHAR2(50)
, address     VARCHAR2(250)
, location_id VARCHAR2(20)
, class       VARCHAR2(3)
, signup_date DATE
, CONSTRAINT cust_pk PRIMARY KEY(cust_id, signup_date)
)
TABLESPACE SET ts1
PARTITION BY CONSISTENT HASH (cust_id)
SUBPARTITION BY RANGE (signup_date)
SUBPARTITION TEMPLATE 
( SUBPARTITION per1 VALUES LESS THAN (TO_DATE('01/01/2000','DD/MM/YYYY')),
  SUBPARTITION per2 VALUES LESS THAN (TO_DATE('01/01/2010','DD/MM/YYYY')),
  SUBPARTITION per3 VALUES LESS THAN (TO_DATE('01/01/2020','DD/MM/YYYY')),
  SUBPARTITION future VALUES LESS THAN (MAXVALUE))
)
PARTITIONS AUTO
;

次の図は、この文によって作成される表を示しています。

図4-5 親パーティションの表領域に格納されるサブパーティション

図4-5の説明が続きます
「図4-5 親パーティションの表領域に格納されるサブパーティション」の説明

この例では、各サブパーティションが親パーティションの表領域に格納されます。日付によってサブパーティション化されているため、サブパーティションを個別の表領域に格納して、古いデータをアーカイブしたり、読取り専用の記憶域に移動できるようにするほうが合理的です。適切な構文を次に示します。

CREATE SHARDED TABLE customers 
( cust_id     NUMBER NOT NULL
, name        VARCHAR2(50)
, address     VARCHAR2(250) 
, location_id VARCHAR2(20)
, class       VARCHAR2(3)
, signup_date DATE NOT NULL
 , CONSTRAINT cust_pk PRIMARY KEY(cust_id, signup_date)
)
PARTITION BY CONSISTENT HASH (cust_id)
SUBPARTITION BY RANGE(signup_date)
SUBPARTITION TEMPLATE 
( SUBPARTITION per1 VALUES LESS THAN (TO_DATE('01/01/2000','DD/MM/YYYY'))
       TABLESPACE SET ts1,
  SUBPARTITION per2 VALUES LESS THAN (TO_DATE('01/01/2010','DD/MM/YYYY'))
       TABLESPACE SET ts2,
  SUBPARTITION per3 VALUES LESS THAN (TO_DATE('01/01/2020','DD/MM/YYYY'))
       TABLESPACE SET ts3,
  SUBPARTITION future VALUES LESS THAN (MAXVALUE)) 
       TABLESPACE SET ts4
)
PARTITIONS AUTO
;

シャーディングされていないデータベースの場合は、サブパーティション・テンプレートで表領域を指定すると、すべてのパーティションのサブパーティションNが同じ表領域に格納されることに注意してください。これは、シャーディングされている場合に、異なるパーティションに属するサブパーティションを個別の表領域に格納して、再シャーディングの際に移動できるようにする場合とは異なります。

サブパーティション化はコンポジット・シャーディングでも使用できます。この場合、表のデータがパーティション・セット、パーティションおよびサブパーティションの3つのレベルに編成されます。次に、3つのレベルにデータを編成する例を示します。

パーティションセット間でサブパーティションの数と境界を均一にするため、パーティションセット単位でのサブパーティション・テンプレートの指定はサポートされていません。パーティションセット単位でサブパーティションの表領域を指定する必要がある場合は、SUBPARTITIONS STORE IN句を使用できます。

CREATE SHARDED TABLE customers 
( cust_id     NUMBER NOT NULL
, name        VARCHAR2(50)
, address     VARCHAR2(250) 
, location_id VARCHAR2(20)
, class       VARCHAR2(3) NOT NULL
, signup_date DATE NOT NULL
, CONSTRAINT cust_pk PRIMARY KEY(cust_id, class, signup_date)
)
PARTITIONSET BY LIST (class)
PARTITION BY CONSISTENT HASH (cust_id)
SUBPARTITION BY RANGE (signup_date)
  SUBPARTITION TEMPLATE /* applies to both SHARDSPACEs */
  ( SUBPARTITION per1 VALUES LESS THAN (TO_DATE('01/01/2000','DD/MM/YYYY'))
  , SUBPARTITION per2 VALUES LESS THAN (TO_DATE('01/01/2010','DD/MM/YYYY'))
  , SUBPARTITION per3 VALUES LESS THAN (TO_DATE('01/01/2020','DD/MM/YYYY'))
  , SUBPARTITION future VALUES LESS THAN (MAXVALUE)
)
PARTITIONS AUTO
(
  PARTITIONSET gold   VALUES (‘gld’) TABLESPACE SET tbs1
 subpartitions store in(tbs1)
, PARTITIONSET silver VALUES (‘slv’) TABLESPACE SET tbs2
 subpartitions store in(tbs2)
)
;

この例では、サブパーティションが親パーティションの表領域に格納され、サブパーティション・テンプレートは各PARTITIONSETで同じです。サブパーティションを個別の表領域に格納するために、次の構文を使用できます。

CREATE SHARDED TABLE customers 
( cust_id     NUMBER NOT NULL
, name        VARCHAR2(50)
, address     VARCHAR2(250) 
, location_id VARCHAR2(20)
, class       VARCHAR2(3) NOT NULL
, signup_date DATE NOT NULL
, CONSTRAINT cust_pk PRIMARY KEY(class, cust_id, signup_date)
)
PARTITIONSET BY LIST (class)
PARTITION BY CONSISTENT HASH (cust_id)
SUBPARTITION BY RANGE (signup_date)
PARTITIONS AUTO
 (
  PARTITIONSET gold   VALUES (‘gld’)
   SUBPARTITION TEMPLATE
   ( SUBPARTITION per1 VALUES LESS THAN (TO_DATE('01/01/2000','DD/MM/YYYY'))
      TABLESPACE SET tbs1
   , SUBPARTITION per2 VALUES LESS THAN (TO_DATE('01/01/2010','DD/MM/YYYY')) 
      TABLESPACE SET tbs2
   , SUBPARTITION per3 VALUES LESS THAN (TO_DATE('01/01/2020','DD/MM/YYYY')) 
      TABLESPACE SET tbs3
   , SUBPARTITION future VALUES LESS THAN (MAXVALUE)) 
      TABLESPACE SET tbs4 
   )
, PARTITIONSET silver VALUES (‘slv’) TABLESPACE SET ts1
   SUBPARTITION TEMPLATE
   ( SUBPARTITION per1 VALUES LESS THAN (TO_DATE('01/01/2000','DD/MM/YYYY'))
      TABLESPACE SET tbs5
   , SUBPARTITION per2 VALUES LESS THAN (TO_DATE('01/01/2010','DD/MM/YYYY')) 
      TABLESPACE SET tbs6
   , SUBPARTITION per3 VALUES LESS THAN (TO_DATE('01/01/2020','DD/MM/YYYY')) 
      TABLESPACE SET tbs7
   , SUBPARTITION future VALUES LESS THAN (MAXVALUE)) 
      TABLESPACE SET tbs8 
   )
)
;