パーティショニングとMySQLの痛み

先日、パーティション分割をしなければなりませんでした。 毎日100万件のレコードがテーブルに追加され、これらのレコードはさまざまなレポートやグラフを提供するために取得されることが予想されます。



サイトを次のようにBitrixに正常にパーティション分割する前に、これを行うのはこれが初めてではないことをすぐに言わなければなりません。



手順1. b_iblock_elementテーブルからAUTO INCREMENTを削除します。

ALTER TABLE b_iblock_element MODIFY ID INT(11)NOT NULL


手順2.テーブルからPRIMARYキーを削除します。

ALTER TABLE b_iblock_element DROP PRIMARY KEY


手順3.パーティション分割の実行に応じて、以前のキーとIBLOCK_IDを含む新しいPRIMARY KEYを作成します。

ALTER TABLE b_iblock_element ADD CONSTRAINT id_iblock_id PRIMARY KEY(ID、IBLOCK_ID)


ステップ4.自動インクリメントを返します。

ALTER TABLE b_iblock_element MODIFY ID INT(11)NOT NULL AUTO_INCREMENT


ステップ5.最後に、10の部分に分解します。

ALTER TABLE b_iblock_element PARTITION BY HASH(IBLOCK_ID)PARTITIONS 10;




すべてが非常に簡単です。 パーティショニング機能にはキーが含まれている場合がありますが、これらのキーはすべてプライマリキーに含まれている必要があります。



今、私は別のテーブルを分割しなければならなかった、そしてそれを一度に2つのフィールドに分割したい:タイプと日付で。 さらに、日付を月単位で区切り、1年以内のデータを保存したかったのです。



ステップ1.最初に出会ったのは、すべての外部キーを削除しなければならなかったことです。 パーティション化するとき、Mysqlはそれらで動作しません。

ALTER TABLE table_name DROP CONSTRAINT fk_key_name


ステップ2.タイムスタンプフィールドをdatetimeに変更する必要がありました。 MySQLはタイムスタンプで誓約しました

エラー1486(HY000):(サブ)パーティション関数の定数、ランダム、またはタイムゾーン依存の式は許可されません


ALTER TABLE table_name CHANGE `date`` date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP;


ステップ3. PRIMARY KEYに日付とタイプのフィールドを追加する必要がありました。



ステップ4.サブパーティションを使用して2つのフィールドに分割することにしました



ALTER TABLE table_data PARTITION BY LIST(月( `date`))

ハッシュによる分割( `type_id`)分割10



パーティションp1の値(1)、

パーティションp2の値(2)、

パーティションp3の値(3)、

パーティションp4の値(4)、

パーティションp5の値(5)、

パーティションp6の値(6)、

パーティションp7の値(7)、

パーティションp8の値(8)、

パーティションp9の値(9)、

パーティションp10の値(10)、

パーティションp11の値(11)、

パーティションp12の値(12)

);




しかし、 MySQLはパーティショニングのためにMONTH機能をサポートし、 LIST / RANGEをHASH / KEYと併用します。つまり、MySQLサブパーティションはこのレベルでのみサポートしますが、成功しませんでした。



クエリのパーティションの説明コマンドは、日付で間隔を選択すると、すべてのパーティションが使用されることを示しました。 Googleは 、MONTH関数は使用できないが、TO_DAYS、YEAR、TO_SECONDS関数のみが使用できると言った。 私はまだパーティションを静的にする必要がありました:



ALTER TABLE table_data PARTITION BY RANGE(to_days( `date`))

ハッシュによる分割( `type_id`)分割10



PARTITION p01 VALUES LESS THAN(to_days( '2015-10-01'))、

PARTITION p02 VALUES LESS THAN(to_days( '2015-11-01'))、

パーティションp03以下の値(to_days( '2015-12-01'))、

PARTITION p04 VALUES LESS THAN(to_days( '2016-01-01'))、

PARTITION p05 VALUES LESS THAN(to_days( '2016-02-01'))、

PARTITION p06 VALUES LESS THAN(to_days( '2016-03-01'))、

パーティションp07値が次の値よりも小さい(to_days( '2016-04-01'))、

パーティションp08以下の値(to_days( '2016-05-01'))、

パーティションp09以下の値(to_days( '2016-06-01'))、

パーティションp10以下の値(to_days( '2016-07-01'))、

PARTITION p11 VALUES LESS THAN(to_days( '2016-08-01'))、

PARTITION p12 VALUES LESS THAN(to_days( '2016-09-01'))、

パーティションp13以下の値(to_days( '2016-10-01'))、

パーティションp14未満の値(to_days( '2016-11-01'))、

PARTITION p15 VALUES LESS THAN(to_days( '2016-12-01'))、

PARTITION p16 VALUES LESS THAN(to_days( '2017-01-01'))、

PARTITION p18 VALUES LESS THAN(to_days( '2017-02-01'))、

パーティションp19以下の値(to_days( '2017-03-01'))、

PARTITION p20 VALUES LESS THAN(to_days( '2017-04-01'))、

パーティションpmaxval値がmaxvalue未満

);




Explain Partitionsチームは、最終的に、大量のテーブルを使用しないことを示しました。 うまくいけば、これが機能し、MySQLがもたらした痛みに感謝します。



All Articles