このセクションでは パーティションの刈り込み を紹介します。この最適化は、MySQL 5.1.6.でパーティショニングされたテーブル用に実装されています。
パーティション刈り込みのコンセプトは単純です。「合致する値が存在し得ないパーティションはスキャンしない」
というものです。例えば、以下のステートメントに定義されたパーティショニングされたテーブル
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 fname, lname, postcode, 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
)
ケース1の場合、オプティマイザは単純に与えられた値のパーティショニング表現を評価し、どのパーティションにその値があるかを判定、そしてそのパーティションのみを検索します。ケース2の場合、オプティマイザはリストに含まれる各値に対してパーティショニング表現を評価し一致するパーティションのリストを作成、そしてそのリストにあるパーティションだけを検索します。
刈り込みはショートレンジにも適用できます。この際、オプティマイザは値が等価のリストに変換できます。例えば、前の例では、WHERE
節は WHERE region_code IN (125, 126, 127, 128, 129,
130)
に変換できます。この後、オプティマイザはリストに含まれる最初の3つの値が
p1
パーティションに含まれると断定、残りの3つの値が
p2
そして、他のパーティションには一致する値が含まれないと判断できるため、残りの検索を省くことができます。
この類の最適化はパーティショニング表現が等価もしくはレンジにより構成され、等価のセットに縮小できる場合、あるいはパーティショニング表現が増減する関係を表している場合に適用できます。刈り込みは
DATE
や DATETIME
カラムでパーティショニングされたテーブルに対しても適用することができます。この時、パーティショニング表現は
YEAR()
または TO_DAYS()
関数を使用しています。(注:将来的にリリースされるMySQLには刈り込みサポートを追加する予定があります。これは、DATE
、DATETIME
値、整数を返し、増減に対して追加関数を行う形になります。)例えば、以下の様に定義されたテーブル
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'; SELECT * FROM t2 WHERE dob BETWEEN '1991-02-15' AND '1997-04-25'; SELECT * FROM t2 WHERE YEAR(dob) IN (1979, 1980, 1983, 1985, 1986, 1988); SELECT * FROM t2 WHERE dob >= '1984-06-21' AND dob <= '1999-06-21'
最後のクエリに関しては、オプティマイザは以下の様に作動します。
レンジの下辺を含むパーティションを検索することができます。.
YEAR('1984-06-21')
は
1984
の値を生み出し、d3
パーティションで発見されます。
レンジの上辺を含むパーティションを検索することができます。.
YEAR('21.06.99')
は
1999
の値を生み出し、d5
パーティションで発見されます。
これら2つのパーティションと、それらの間にあるパーティションのみを検索します。.
この場合、パーティション
d3
、d4
、d5
のみが検索されます。残りのパーティションは安全に無視することができます。(無視されます。)
これまで、RANGE
パーティショニングを含む例のみを挙げましたが、刈り込みは他のパーティショニングのタイプでも利用することができます。
LIST
によってパーティショニングされたテーブルを検討します。パーティショニング表現が増減を繰り返している、以下のようなテーブル
t3
を検証してみましょう。(この例では、詳細を省くため
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
や 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;
このようなクエリは全て刈り込みの対象となります。
SELECT * FROM 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)
に変更されます。重要この最適化はレンジの規模がパーティションの数よりも小さい場合のみ使用されます。このクエリを検討してください。
SELECT * FROM t4 WHERE region_code BETWEEN 4 AND 8;
WHERE
節のレンジは5つの値ををカバーします(4, 5, 6, 7,
8)。しかし、t4
には4つのパーティションしか存在しません。これは、以前のクエリを刈り込みできないことを意味しています。
刈り込みは HASH
や KEY
によってパーティショニングされたテーブルの整数カラムにのみ使用できます。例えば、テーブル
t4
のクエリは、dob
が
DATE
カラムであるため、刈り込みを使用することができません。
SELECT * FROM t4 WHERE dob >=- '2001-04-14' AND dob <= '2005-10-15';
ただし、テーブルが INT
カラム内で年度を示す値を記憶している場合、WHERE
year_col >= 2001 AND year_col <= 2005
を含むクエリは刈り込みされます。