範囲によってパーティション化されるテーブルは、各パーティションに含まれる行のパーティショニング式値が指定された範囲に収まるようにパーティション化されます。 範囲は、連続しているけれども重複しないものであるべきで、VALUES LESS THAN
演算子を使用して定義されます。 次のいくつかの例では、20 のビデオ店で構成されるチェーン (1 から 20 までの番号が付けられている) の従業員レコードを保持する、次のようなテーブルを作成していると想定してください。
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 NOT NULL,
store_id INT NOT NULL
);
ここで使用する employees
テーブルには主キーまたは一意キーがありません。 これらの例はここでの説明のためのもので、実際のテーブルは主キー、一意キー、またはその両方を備えている可能性がきわめて高く、パーティショニングカラムに利用できる選択肢はこれらのキー (ある場合) に使用されるカラムに依存します。 これらの事項については、セクション24.6.1「パーティショニングキー、主キー、および一意キー」を参照してください。
このテーブルは、必要に応じていくつかの方法で、範囲によるパーティション化を実行できます。 1 つの方法は、store_id
カラムを使用することです。 たとえば、次のように PARTITION BY RANGE
句を追加することで、テーブルを 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 NOT NULL,
store_id INT NOT NULL
)
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (6),
PARTITION p1 VALUES LESS THAN (11),
PARTITION p2 VALUES LESS THAN (16),
PARTITION p3 VALUES LESS THAN (21)
);
このパーティショニングスキームでは、店舗 1 から店舗 5 で働いている従業員に対応するすべての行がパーティション p0
に格納され、店舗 6 から店舗 10 の従業員がパーティション p1
に格納されます (以下同様)。 各パーティションは、最低から最高の順に定義されます。 これは PARTITION BY RANGE
構文の要件です。これは、C または Java の一連の if ... elseif ...
ステートメントに似ていると考えることができます。
(72, 'Mitchell', 'Wilson', '1998-06-25', NULL, 13)
データを含む新しい行がパーティション p2
に挿入されたことを簡単に判別できますが、チェーンで 21 の st ストアが追加されるとどうなりますか。 このスキームでは、store_id
が 20 よりも大きい行に対応するルールがなく、サーバーはどこに置くべきかがわからないため、エラーになります。 これが発生しないようにするには、「すべての状況に対応する」 VALUES LESS THAN
句を CREATE TABLE
ステートメントで使用して、明示的に指定されている最大値を超えるすべての値に備えます。
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 NOT NULL,
store_id INT NOT NULL
)
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (6),
PARTITION p1 VALUES LESS THAN (11),
PARTITION p2 VALUES LESS THAN (16),
PARTITION p3 VALUES LESS THAN MAXVALUE
);
(この章のその他の例と同様に、デフォルトのストレージエンジンは InnoDB
であると想定しています。)
一致する値が見つからないときにエラーを回避するための別の方法は、INSERT
ステートメントの一部として IGNORE
キーワードを使用することです。 例については、セクション24.2.2「LIST パーティショニング」を参照してください。 また、IGNORE
の一般的な情報については、セクション13.2.6「INSERT ステートメント」を参照してください。
MAXVALUE
は、可能な最大整数値よりも確実に大きな整数値を表します (数学用語では、上限です)。 これによって、store_id
カラム値が 16 (定義されている最大値) 以上である行は、パーティション p3
に格納されます。 将来のある時点で、店舗の数が 25、30、またはそれ以上に増加したときは、ALTER TABLE
ステートメントを使用して、店舗 21-25、26-30 などのための新しいパーティションを追加できます (これを行う方法の詳細については、セクション24.3「パーティション管理」を参照してください)。
同様に、従業員ジョブコードに基づいて (つまり、job_code
カラム値の範囲に基づいて) テーブルをパーティション化できます。 たとえば、正規 (インストア) 従業員に 2 桁のジョブコード、オフィスおよびサポート従業員に 3 桁のコード、および管理職に 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 NOT NULL,
store_id INT NOT NULL
)
PARTITION BY RANGE (job_code) (
PARTITION p0 VALUES LESS THAN (100),
PARTITION p1 VALUES LESS THAN (1000),
PARTITION p2 VALUES LESS THAN (10000)
);
この例では、インストア従業員に関連するすべての行はパーティション p0
、オフィスおよびサポートスタッフに関連するものは p1
、および管理職に関連するものはパーティション p2
に格納されます。
VALUES LESS THAN
句に式を使用することもできます。 ただし、MySQL は、LESS THAN
(<
) 比較の一環として式の戻り値を評価できる必要があります。
店舗番号に従ってテーブルデータを分割するのではなく、代わりに 2 つの DATE
カラムのうちの 1 つに基づく式を使用できます。 たとえば、各従業員が会社を退職した年 (つまり、YEAR(separated)
の値) に基づいてパーティション化するとします。 そのようなパーティショニングスキームを実装する CREATE TABLE
ステートメントの例を次に示します。
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 RANGE ( YEAR(separated) ) (
PARTITION p0 VALUES LESS THAN (1991),
PARTITION p1 VALUES LESS THAN (1996),
PARTITION p2 VALUES LESS THAN (2001),
PARTITION p3 VALUES LESS THAN MAXVALUE
);
このスキームでは、1991 年より前に退職したすべての従業員の場合、行はパーティション p0
に格納されます。1991 年から 1995 年までに退職した人は p1
、1996 年から 2000 年までに退職した人は p2
、および 2000 年よりあとに退職した従業員は p3
に格納されます。
次の例に示すように、UNIX_TIMESTAMP()
関数を使用して、TIMESTAMP
カラムの値に基づいて、RANGE
によってテーブルをパーティション化することもできます。
CREATE TABLE quarterly_report_status (
report_id INT NOT NULL,
report_status VARCHAR(20) NOT NULL,
report_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
PARTITION BY RANGE ( UNIX_TIMESTAMP(report_updated) ) (
PARTITION p0 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-01-01 00:00:00') ),
PARTITION p1 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-04-01 00:00:00') ),
PARTITION p2 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-07-01 00:00:00') ),
PARTITION p3 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-10-01 00:00:00') ),
PARTITION p4 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-01-01 00:00:00') ),
PARTITION p5 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-04-01 00:00:00') ),
PARTITION p6 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-07-01 00:00:00') ),
PARTITION p7 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-10-01 00:00:00') ),
PARTITION p8 VALUES LESS THAN ( UNIX_TIMESTAMP('2010-01-01 00:00:00') ),
PARTITION p9 VALUES LESS THAN (MAXVALUE)
);
TIMESTAMP
値を含むほかの式は許可されません (Bug #42849 を参照してください)。
次の条件の 1 つ以上が true のときは、RANGE パーティショニングが特に役立ちます。
「古い」データを削除したい、またはする必要がある。 前述の
employees
テーブルのパーティション化スキームを使用している場合は、ALTER TABLE employees DROP PARTITION p0;
を使用して、1991 年より前に企業の勤務を停止した従業員に関連するすべての行を削除できます。 (詳細は、セクション13.1.9「ALTER TABLE ステートメント」およびセクション24.3「パーティション管理」を参照してください)。 テーブルに多数の行がある場合、これはDELETE FROM employees WHERE YEAR(separated) <= 1990;
などのDELETE
クエリーを実行するよりもはるかに効率的な場合があります。日付または時間値、または何らかのほかの一連値から生じる値が含まれるカラムを使用したい。
テーブルのパーティショニングに使用されるカラムに直接依存するクエリーを頻繁に実行する。 たとえば、
EXPLAIN SELECT COUNT(*) FROM employees WHERE separated BETWEEN '2000-01-01' AND '2000-12-31' GROUP BY store_id;
などのクエリーを実行する場合、MySQL では、WHERE
句を満たすレコードを残りのパーティションに含めることができないため、パーティションp2
のみをスキャンする必要があると迅速に判断できます。 これがどのように実現されるかについての詳細は、セクション24.4「パーティションプルーニング」を参照してください。
このタイプのパーティショニングのバリアントが RANGE COLUMNS
パーティショニングです。 RANGE COLUMNS
によるパーティショニングでは、複数のカラムを使用してパーティショニング範囲を定義できます (パーティション内での行の配置、およびパーティションプルーニングを実行するときに特定のパーティションの包含または除外を判断する際に適用されます)。 詳細は、セクション24.2.3.1「RANGE COLUMNS パーティショニング」を参照してください。
時間間隔に基づくパーティショニングスキーム. MySQL 8.0 で時間の範囲または間隔に基づいてパーティショニングスキームを実装する場合は、2 つの方法があります。
-
次のように、
RANGE
によってテーブルをパーティション化し、パーティショニング式にDATE
、TIME
、またはDATETIME
カラムを操作して整数値を返す関数を使用します。CREATE TABLE members ( firstname VARCHAR(25) NOT NULL, lastname VARCHAR(25) NOT NULL, username VARCHAR(16) NOT NULL, email VARCHAR(35), joined DATE NOT NULL ) PARTITION BY RANGE( YEAR(joined) ) ( PARTITION p0 VALUES LESS THAN (1960), PARTITION p1 VALUES LESS THAN (1970), PARTITION p2 VALUES LESS THAN (1980), PARTITION p3 VALUES LESS THAN (1990), PARTITION p4 VALUES LESS THAN MAXVALUE );
MySQL 8.0 では、次の例に示すように
UNIX_TIMESTAMP()
関数を使用して、TIMESTAMP
カラムの値に基づいてRANGE
によってテーブルをパーティション化することもできます。CREATE TABLE quarterly_report_status ( report_id INT NOT NULL, report_status VARCHAR(20) NOT NULL, report_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) PARTITION BY RANGE ( UNIX_TIMESTAMP(report_updated) ) ( PARTITION p0 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-01-01 00:00:00') ), PARTITION p1 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-04-01 00:00:00') ), PARTITION p2 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-07-01 00:00:00') ), PARTITION p3 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-10-01 00:00:00') ), PARTITION p4 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-01-01 00:00:00') ), PARTITION p5 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-04-01 00:00:00') ), PARTITION p6 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-07-01 00:00:00') ), PARTITION p7 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-10-01 00:00:00') ), PARTITION p8 VALUES LESS THAN ( UNIX_TIMESTAMP('2010-01-01 00:00:00') ), PARTITION p9 VALUES LESS THAN (MAXVALUE) );
MySQL 8.0 では、
TIMESTAMP
値を含むほかの式は許可されません。 (Bug #42849 を参照してください)。注記MySQL 8.0 では、
LIST
によってパーティション化されるテーブルのパーティショニング式としてUNIX_TIMESTAMP(timestamp_column)
を使用することもできます。 ただし、このようにするのは通常は実用的ではありません。 -
DATE
またはDATETIME
カラムをパーティショニングカラムとして使用して、RANGE COLUMNS
によってテーブルをパーティション化します。 たとえば、次のようにjoined
カラムを直接使用してmembers
テーブルを定義できます。CREATE TABLE members ( firstname VARCHAR(25) NOT NULL, lastname VARCHAR(25) NOT NULL, username VARCHAR(16) NOT NULL, email VARCHAR(35), joined DATE NOT NULL ) PARTITION BY RANGE COLUMNS(joined) ( PARTITION p0 VALUES LESS THAN ('1960-01-01'), PARTITION p1 VALUES LESS THAN ('1970-01-01'), PARTITION p2 VALUES LESS THAN ('1980-01-01'), PARTITION p3 VALUES LESS THAN ('1990-01-01'), PARTITION p4 VALUES LESS THAN MAXVALUE );
DATE
または DATETIME
以外の日付または時間型を使用してパーティショニングカラムを使用することは、RANGE COLUMNS
ではサポートされません。