Documentation Home
MySQL 5.6 リファレンスマニュアル
Download this Manual
EPUB - 7.5Mb
HTML Download (TGZ) - 7.2Mb
HTML Download (Zip) - 7.2Mb


MySQL 5.6 リファレンスマニュアル  /  パーティション化  /  パーティションプルーニング

19.4 パーティションプルーニング

このセクションでは、パーティションプルーニングと呼ばれる最適化について説明します。パーティションプルーニングの背後の中心概念は比較的単純で、一致する値がないパーティションはスキャンしないと表現できます。次のステートメントによって定義されたパーティション化されたテーブル t1 があるとします。

CREATE TABLE t1 (
    fname VARCHAR(50) NOT NULL,
    lname VARCHAR(50) NOT NULL,
    region_code TINYINT UNSIGNED NOT NULL,
    dob DATE NOT NULL
)
PARTITION BY RANGE( region_code ) (
    PARTITION p0 VALUES LESS THAN (64),
    PARTITION p1 VALUES LESS THAN (128),
    PARTITION p2 VALUES LESS THAN (192),
    PARTITION p3 VALUES LESS THAN MAXVALUE
);

次のような SELECT ステートメントから結果を取得するとします。

SELECT fname, lname, region_code, dob
    FROM t1
    WHERE region_code > 125 AND region_code < 130;

返すべき行がパーティション p0 にも p3 にもないことは簡単にわかります。つまり、パーティション p1 および p2 のみを検索して一致する行を見つける必要があります。そうすることにより、一致する行を検索するために消費する時間と労力が、テーブル内のすべてのパーティションのスキャンに必要なものより少なくて済みます。必要のないパーティションをこのように省くことをプルーニングといいます。オプティマイザがこのクエリーの実行でパーティションプルーニングを使用できるときは、同じカラム定義およびデータが含まれているパーティション化されていないテーブルで同じクエリーを実行するよりも、速度が大幅に向上することがあります。

WHERE 条件を次の 2 つのケースのいずれかにまとめられるとき、オプティマイザはプルーニングを実行できます。

  • partition_column = constant

  • partition_column IN (constant1, constant2, ..., constantN)

最初のケースで、オプティマイザは指定された値についてパーティショニング式を単純に評価し、どのパーティションに値が含まれるかを判別して、このパーティションのみをスキャンします。多くの場合、この等号を別の算術比較 (<><=>=、および <> を含む) に置き換えることができます。WHERE 句で BETWEEN を使用するクエリーも、パーティションプルーニングの利点を活用できます。このセクションの後続の例を参照してください。

2 番目のケースで、オプティマイザはリスト内の各値についてパーティショニング式を評価して、一致するパーティションのリストを作成してから、このパーティションリストのパーティションのみをスキャンします。

MySQL は、パーティションプルーニングを SELECTDELETE、および UPDATE ステートメントに適用できます。INSERT ステートメントは現在のところ、プルーニングできません。

短い範囲にもプルーニングを適用できます (オプティマイザが同等の値リストに変換できるもの)。たとえば、前の例では、WHERE 句を WHERE region_code IN (126, 127, 128, 129) に変換できます。これにより、オプティマイザは、リスト内の最初の 3 つの値はパーティション p1 に見つかり、残りの 3 つの値はパーティション p2 に見つかり、ほかのパーティションには関連する値は含まれないため一致する行を検索する必要がないと判断できます。

MySQL 5.6 のオプティマイザは、RANGE COLUMNS または LIST COLUMNS パーティショニングを使用するテーブルの複数のカラムで、前述のタイプの比較を使用する WHERE 条件のプルーニングを実行することもできます。

このタイプの最適化は、パーティショニング式が同一性や範囲で構成されていてそれを同一性のセットにまとめられるとき、またはパーティショニング式が増減する関係を表すときに適用できます。パーティショニング式が YEAR() または TO_DAYS() 関数を使用するとき、DATE カラムまたは DATETIME カラムでパーティション化されるテーブルにプルーニングを適用することもできます。また、MySQL 5.6 では、パーティショニング式が TO_SECONDS() 関数を使用するとき、そのようなテーブルにプルーニングを適用できます。

テーブル t2 が次のように定義されて、DATE カラムでパーティション化されるとします。

CREATE TABLE t2 (
    fname VARCHAR(50) NOT NULL,
    lname VARCHAR(50) NOT NULL,
    region_code TINYINT UNSIGNED NOT NULL,
    dob DATE NOT NULL
)
PARTITION BY RANGE( YEAR(dob) ) (
    PARTITION d0 VALUES LESS THAN (1970),
    PARTITION d1 VALUES LESS THAN (1975),
    PARTITION d2 VALUES LESS THAN (1980),
    PARTITION d3 VALUES LESS THAN (1985),
    PARTITION d4 VALUES LESS THAN (1990),
    PARTITION d5 VALUES LESS THAN (2000),
    PARTITION d6 VALUES LESS THAN (2005),
    PARTITION d7 VALUES LESS THAN MAXVALUE
);

t2 を使用する次のステートメントでは、パーティションプルーニングを使用できます。

SELECT * FROM t2 WHERE dob = '1982-06-23';

UPDATE t2 SET region_code = 8 WHERE dob BETWEEN '1991-02-15' AND '1997-04-25';

DELETE FROM t2 WHERE dob >= '1984-06-21' AND dob <= '1999-06-21'

最後のステートメントの場合、オプティマイザは次のようにも動作できます。

  1. 範囲の下限が含まれるパーティションを見つけます

    YEAR('1984-06-21') は値 1984 を返し、それはパーティション d3 に見つかります。

  2. 範囲の上限が含まれるパーティションを見つけます

    YEAR('1999-06-21')1999 と評価され、それはパーティション d5 に見つかります。

  3. これらの 2 つのパーティションおよびそれらの間にある可能性のあるパーティションのみをスキャンします

    この場合、これはパーティション d3d4、および d5 のみがスキャンされることを意味します。残りのパーティションは安全に無視できます (そして無視されます)。

重要

パーティション化されたテーブルに対するステートメントの WHERE 条件で参照される無効な DATE および DATETIME 値は、NULL として扱われます。これは、SELECT * FROM partitioned_table WHERE date_column < '2008-12-00' などのクエリーは値を返さないことを意味します (Bug #40972 を参照してください)。

ここまで、RANGE パーティショニングを使用する例のみを見てきましたが、プルーニングはほかのパーティショニングタイプにも適用できます。

次に示すテーブル t3 のように、パーティショニング式が増加または減少している LIST によってパーティション化されたテーブルがあるとします。(この例では、簡単にするために region_code カラムが値 1 から 10 まで (両端を含む) に制限されると想定します)。

CREATE TABLE t3 (
    fname VARCHAR(50) NOT NULL,
    lname VARCHAR(50) NOT NULL,
    region_code TINYINT UNSIGNED NOT NULL,
    dob DATE NOT NULL
)
PARTITION BY LIST(region_code) (
    PARTITION r0 VALUES IN (1, 3),
    PARTITION r1 VALUES IN (2, 5, 8),
    PARTITION r2 VALUES IN (4, 9),
    PARTITION r3 VALUES IN (6, 7, 10)
);

SELECT * FROM t3 WHERE region_code BETWEEN 1 AND 3 などのステートメントの場合、オプティマイザはどのパーティションで値 1、2、および 3 が見つかるかを判別して (r0 および r1)、残りのもの (r2 および r3) をスキップします。

HASH または [LINEAR] KEY によってパーティション化されたテーブルの場合も、パーティショニング式で使用されるカラムに対して WHERE 句が単純な = 関係を使用しているときは、パーティションプルーニングを適用できます。次のように作成されたテーブルがあるとします。

CREATE TABLE t4 (
    fname VARCHAR(50) NOT NULL,
    lname VARCHAR(50) NOT NULL,
    region_code TINYINT UNSIGNED NOT NULL,
    dob DATE NOT NULL
)
PARTITION BY KEY(region_code)
PARTITIONS 8;

カラム値を定数と比較するステートメントはプルーニングできます。

UPDATE t4 WHERE region_code = 7;

プルーニングは短い範囲にも適用できます。オプティマイザがそのような条件を IN 関係に変換できるためです。たとえば、前に定義したものと同じテーブル t4 を使用して、次のようなクエリーをプルーニングできます。

SELECT * FROM t4 WHERE region_code > 2 AND region_code < 6;

SELECT * FROM t4 WHERE region_code BETWEEN 3 AND 5;

どちらの場合も、WHERE 句はオプティマイザによって WHERE region_code IN (3, 4, 5) に変換されます。

重要

この最適化は、範囲サイズがパーティションの数より小さい場合にのみ使用されます。次のステートメントがあるとします。

DELETE FROM t4 WHERE region_code BETWEEN 4 AND 12;

WHERE 句の範囲は 9 個の値 (4、5、6、7、8、9、10、11、12) ですが、t4 のパーティションは 8 個だけです。これはこの DELETE をプルーニングできないことを意味します。

HASH または [LINEAR] KEY によってパーティション化されたテーブルの場合、プルーニングを使用できるのは整数カラムに対してのみです。たとえば、dobDATE カラムであるため、次のステートメントにはプルーニングを使用できません。

SELECT * FROM t4 WHERE dob >= '2001-04-14' AND dob <= '2005-10-15';

ただし、このテーブルが年値を INT カラムに格納する場合は、WHERE year_col >= 2001 AND year_col <= 2005 を持つクエリーをプルーニングできます。

MySQL 5.6.8 以降では、自動パーティショニングを提供するストレージエンジン (MySQL Cluster によって使用される NDB ストレージエンジン (現在のところ、MySQL 5.6 ではサポートされません) など) を使用するすべてのテーブルで、パーティションプルーニングは無効です(Bug #14672885)。MySQL 5.6.10 以降では、明示的にパーティション化されている場合は、そのようなテーブルをプルーニングできます(Bug #14827952)。


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