19.2.4 HASH パーティショニング

HASH によるパーティショニングは、事前に決められた数のパーティションにデータを均等に配分するために主に使用されます。RANGE または LIST パーティショニングでは、指定されたカラム値またはカラム値セットがどのパーティションに格納されるかを明示的に指定する必要があります。HASH パーティショニングでは MySQL がこれを自動的に行うため、必要なことは、ハッシュされるカラム値またはカラム値に基づく式、およびパーティション化されたテーブルがいくつのパーティションに分割されるかを指定することだけです。

HASH パーティショニングを使用してテーブルをパーティション化する場合は、CREATE TABLE ステートメントに PARTITION BY HASH (expr) 句を付加する必要があります。ここで、expr は整数を返す式です。これには、型が MySQL の整数型のいずれかであるカラムの名前を単純に指定できます。また、これのあとにはほとんどの場合 PARTITIONS num 句を続けます。ここで、num はテーブルがいくつのパーティションに分割されるかを表す正の整数です。

たとえば、次のステートメントは store_id カラムにハッシュを使用し、4 つのパーティションに分割されたテーブルを作成します。

CREATE TABLE employees (
    id INT NOT NULL,
    fname VARCHAR(30),
    lname VARCHAR(30),
    hired DATE NOT NULL DEFAULT '1970-01-01',
    separated DATE NOT NULL DEFAULT '9999-12-31',
    job_code INT,
    store_id INT
)
PARTITION BY HASH(store_id)
PARTITIONS 4;

PARTITIONS 句を含めない場合、パーティションの数はデフォルトで 1 となります。

PARTITIONS キーワードを使用する場合、そのあとに数を指定しないと構文エラーになります。

整数を返す SQL 式を expr に使用することもできます。たとえば、従業員が雇用された年度に基づいてパーティション化するとします。これは、次のように行うことができます。

CREATE TABLE employees (
    id INT NOT NULL,
    fname VARCHAR(30),
    lname VARCHAR(30),
    hired DATE NOT NULL DEFAULT '1970-01-01',
    separated DATE NOT NULL DEFAULT '9999-12-31',
    job_code INT,
    store_id INT
)
PARTITION BY HASH( YEAR(hired) )
PARTITIONS 4;

expr は、定数以外のランダムではない整数値 (つまり、変化するけれども決定論的であるべき) を返す必要があり、セクション19.6「パーティショニングの制約と制限」で説明されている禁止された構造体を含んでいてはいけません。また、この式は行が挿入または更新 (または場合によっては削除) されるたびに評価されるべきです。これは、非常に複雑な式がパフォーマンスの問題を起こすことがあることを意味します (特に、一度に多くの行に影響する操作 (バッチ挿入など) を実行するとき)。

もっとも効率的なハッシュ関数は、単一テーブルカラムに実行され、その値がカラム値に対して比例的に増加または減少するもので、これによってパーティションの範囲をプルーニングできます。つまり、式がそのベースのカラムの値に対してより密接に変化するほど、MySQL は式を HASH パーティショニングにより効率的に使用できます。

たとえば、date_colDATE 型のカラムである場合、式 TO_DAYS(date_col)date_col の値に正比例すると表現されます。date_col の値が変わるたびに、式の値が一定の方法で変化するためです。date_col に対する式 YEAR(date_col) の変化は、TO_DAYS(date_col) ほど比例的ではありません。date_col のあらゆる変化に対して YEAR(date_col) が同等に変化するとはかぎらないためです。それでも、YEAR(date_col) はハッシュ関数の良い候補の 1 つです。date_col の一部と正比例し、date_col の変化によって YEAR(date_col) で比例的でない変化が発生することがないためです。

比較のために、型が INT である int_col という名前のカラムがあるとします。式 POW(5-int_col,3) + 6 を検討してみてください。これは、int_col の値が変化したときに、式の値に比例的に変化することが保証されないため、ハッシュ関数の良い候選択肢ではありません。int_col の値が一定量で変化したときに、式の値の変化量が大きくなる可能性があります。たとえば、int_col5 から 6 に変化すると、式の値が -1 に変化しますが、int_col の値が 6 から 7 に変化すると、式の値が -7 に変化します。

つまり、カラム値と式の値のグラフが、等式 y=cx (ここで、c はゼロでない何らかの定数) によって描かれるような直線に近くなるほど、その式はハッシュにより適切になります。これは、式が非直線的であるほど、パーティションに対するデータの配分が不均衡になる傾向があることに関係しています。

理論上は、複数のカラム値を使用する式をプルーニングすることもできますが、そのような式のどれが適しているかを判断するのがかなり難しく、時間がかかることがあります。このため、複数のカラムを含むハッシュ式を使用することはあまり推奨されていません。

PARTITION BY HASH が使用された場合、MySQL はユーザー関数の結果の法に基づいて、num パーティションのうちのどのパーティションを使用するかを判断します。つまり、式 expr の場合、レコードが格納されるパーティションは、パーティション番号 N です (ここで、N = MOD(expr, num))。テーブル t1 が次のように 4 つのパーティションを持つように定義されているとします。

CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATE)
    PARTITION BY HASH( YEAR(col3) )
    PARTITIONS 4;

t1col3 値が '2005-09-15' であるレコードを挿入した場合、それが格納されるパーティションは次のように判断されます。

MOD(YEAR('2005-09-01'),4)
=  MOD(2005,4)
=  1

MySQL 5.6 は、パーティション化されたテーブルに挿入される新しい行の配置を判断するために、より複雑なアルゴリズムを使用する線形ハッシュと呼ばれる、HASH パーティショニングのバリアントもサポートします。このアルゴリズムについては、セクション19.2.4.1「LINEAR HASH パーティショニング」を参照してください。

ユーザー関数は、レコードが挿入または更新されるたびに評価されます。状況によっては、レコードが削除されるときにも評価されることがあります。

注記

パーティション化されるテーブルに UNIQUE キーがある場合、HASH ユーザー関数または KEYcolumn_list に引数として指定するカラムは、そのキーの一部である必要があります。


User Comments
Sign Up Login You must be logged in to post a comment.