web-dev-qa-db-ja.com

大きなmysqlテーブルのパーティショニング

パーティション分割したい大きな(40GB)テーブルがあります。行は基本的に、一度読み取って多数回書き込みます。現在、mysql_5.5 innodbとfile_per_tableを使用しています。ファイル全体の再構築には非常に長い時間がかかるため、このテーブルを最適化するのは困難です。

テーブルにパーティションを作成して、書き込まれるパーティションが1つだけになるようにしています。これは、現在の各ファイルが一度だけ最適化され、再度操作する必要がないため、テーブルの最適化にかかる時間が大幅に短縮されることを意味します。

私はmysqlでテーブルパーティションを作成するのが初めてですが、これを行うための正しい方法は何なのかわかりません。私は「ファイルサイズ」のパーティションスキームがないことを知っているので、次善の策は、私が好むファイルサイズになる行の範囲でSwagすることです(3〜4 GBが良いようです。現在のレート)。私の考えはidのパーティションを範囲化することですが、それはファイルパーティションの技術的要件に対応できません(「パーティションテーブルのパーティション式で使用されるすべての列は、テーブルが持つ可能性のあるすべての一意のキーの一部である必要があります。持ってる。")。それで、これに対処する正しい方法は何ですか?以下は、重要な部分にトリミングされたテーブル定義です。

+-----------------+--------------+------+-----+---------+----------------+
| Field           | Type         | Null | Key | Default | Extra          |
+-----------------+--------------+------+-----+---------+----------------+
| id              | int(11)      | NO   | PRI | NULL    | auto_increment |
| TransactionId   | int(11)      | NO   | MUL | NULL    |                |
| Parent          | int(11)      | NO   | MUL | 0       |                |
| Headers         | longtext     | YES  |     | NULL    |                |
| Creator         | int(11)      | NO   |     | 0       |                |
| Created         | datetime     | YES  |     | NULL    |                |
+-----------------+--------------+------+-----+---------+----------------+

時間の経過... mysql.comリポジトリの使用に移行し、5.6にアップグレードしました。裁判の時間です。小さなテーブルを使用して、オンラインDDL最適化を使用しようとしました。期待した結果が得られません:

mysql> optimize table Users;
+-----------+----------+----------+-------------------------------------------------------------------+
| Table     | Op       | Msg_type | Msg_text                                                          |
+-----------+----------+----------+-------------------------------------------------------------------+
| rt4.Users | optimize | note     | Table does not support optimize, doing recreate + analyze instead |
| rt4.Users | optimize | status   | OK                                                                |
+-----------+----------+----------+-------------------------------------------------------------------+
2 rows in set (0.43 sec)

mysql> desc Users;
+-----------------------+--------------+------+-----+---------+----------------+
| Field                 | Type         | Null | Key | Default | Extra          |
+-----------------------+--------------+------+-----+---------+----------------+
| id                    | int(11)      | NO   | PRI | NULL    | auto_increment |
| Name                  | varchar(200) | NO   | UNI | NULL    |                |
| Password              | varchar(256) | YES  |     | NULL    |                |
| AuthToken             | varchar(16)  | YES  |     | NULL    |                |
| Comments              | text         | YES  |     | NULL    |                |
| Signature             | text         | YES  |     | NULL    |                |
| EmailAddress          | varchar(120) | YES  | MUL | NULL    |                |
| FreeformContactInfo   | text         | YES  |     | NULL    |                |
| Organization          | varchar(200) | YES  |     | NULL    |                |
| RealName              | varchar(120) | YES  |     | NULL    |                |
| NickName              | varchar(16)  | YES  |     | NULL    |                |
| Lang                  | varchar(16)  | YES  |     | NULL    |                |
| EmailEncoding         | varchar(16)  | YES  |     | NULL    |                |
| WebEncoding           | varchar(16)  | YES  |     | NULL    |                |
| ExternalContactInfoId | varchar(100) | YES  |     | NULL    |                |
| ContactInfoSystem     | varchar(30)  | YES  |     | NULL    |                |
| ExternalAuthId        | varchar(100) | YES  |     | NULL    |                |
| AuthSystem            | varchar(30)  | YES  |     | NULL    |                |
| Gecos                 | varchar(16)  | YES  |     | NULL    |                |
| HomePhone             | varchar(30)  | YES  |     | NULL    |                |
| WorkPhone             | varchar(30)  | YES  |     | NULL    |                |
| MobilePhone           | varchar(30)  | YES  |     | NULL    |                |
| PagerPhone            | varchar(30)  | YES  |     | NULL    |                |
| Address1              | varchar(200) | YES  |     | NULL    |                |
| Address2              | varchar(200) | YES  |     | NULL    |                |
| City                  | varchar(100) | YES  |     | NULL    |                |
| State                 | varchar(100) | YES  |     | NULL    |                |
| Zip                   | varchar(16)  | YES  |     | NULL    |                |
| Country               | varchar(50)  | YES  |     | NULL    |                |
| Timezone              | varchar(50)  | YES  |     | NULL    |                |
| PGPKey                | text         | YES  |     | NULL    |                |
| Creator               | int(11)      | NO   |     | 0       |                |
| Created               | datetime     | YES  |     | NULL    |                |
| LastUpdatedBy         | int(11)      | NO   |     | 0       |                |
| LastUpdated           | datetime     | YES  |     | NULL    |                |
| SMIMECertificate      | text         | YES  |     | NULL    |                |
+-----------------------+--------------+------+-----+---------+----------------+
36 rows in set (0.00 sec)

mysql> select @@VERSION;
+------------+
| @@VERSION  |
+------------+
| 5.6.19-log |
+------------+
1 row in set (0.00 sec)

何が欠けていますか?

3
Ram

まず、別の方法で問題を解決することを検討する必要があります。

  • InnoDBオンラインDDL でサポートされているため、_OPTIMIZE TABLE_が(InnoDBテーブルの場合)ブロックせずに機能するMySQL 5.6にアップグレードします。

  • アップグレードできない場合は、Percona Toolkitのpt-online-schema-changeを使用してみてください。これにより、ブロックせずにテーブルの再構築を実行できます。

    _$ pt-online-schema-change h=localhost,D=mydatabase,t=mytable --execute
        --alter="ENGINE=InnoDB"
    _

パーティションの使用に行き詰まっている場合は、はい、表示するテーブルのパーティションキーをidにする必要があります。 _ALTER TABLE_を使用して、テーブルをパーティションに変換できます。変換操作を非ブロッキングにする必要がある場合は、pt-online-schema-changeを使用します。

固定サイズのパーティションに分割する方法はありません。値で分割する必要があります。しかし、パーティションごとに特定のサイズに達することは本当に重要ですか?


パーティションサイズに関するコメントを再入力してください:

RANGEパーティショニングを使用する場合、ALTER TABLEのスケジュールを設定し、最後のパーティションを時々分割します。成長率が一定の場合、これは簡単ですが、不規則な成長パターンがある場合は、代わりに、パーティションごとの行数を調べる定期的なチェックを設定することもできます( INFORMATION_SCHEMA.PARTITIONS を使用します)。 =)、いっぱいになったらメールで通知します。

たとえば、idに範囲で分割されたテーブルを設定してみましょう。

_CREATE TABLE `mytable` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `transactionid` int(11) NOT NULL,
  `parent` int(11) NOT NULL,
  `headers` longtext,
  `creator` int(11) NOT NULL,
  `created` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id` (`id`),
  KEY `transactionid` (`transactionid`,`parent`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE (id)
(PARTITION p0 VALUES LESS THAN (0) ENGINE = InnoDB,
 PARTITION p1 VALUES LESS THAN (1000) ENGINE = InnoDB,
 PARTITION p2 VALUES LESS THAN (2000) ENGINE = InnoDB,
 PARTITION p3 VALUES LESS THAN (3000) ENGINE = InnoDB,
 PARTITION p4 VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */
_

MAX(id)が3000に近づくと、_p3_がいっぱいになり、_p4_にオーバーフローします。だから、再編成する時が来ました。 reorgは最後の空のパーティションのみに影響を与えるため、非常に高速になるため、データが_p4_に波及する前にこれを実行することをお勧めします。

_ALTER TABLE mytable REORGANIZE PARTITION p4 INTO 
(PARTITION p4 VALUES LESS THAN (4000), PARTITION p5 VALUES LESS THAN MAXVALUE);
_

一日を逃して古い_p4_にデータを取り込む場合でも、データが少ない可能性があります。ただし、これを1〜2か月間無視し、_p4_が大量のデータでいっぱいになると、REORGANIZEに時間がかかります。

5
Bill Karwin