20,000個のテーブルを作成することは悪い考えです。やがて40,000のテーブルが必要になり、それ以上が必要になります。
私はこの症候群をメタデータトリブルと呼びました 私の本の中で
これは、数万のテーブルがある場合に実際のパフォーマンスの問題を引き起こします。各テーブルでは、MySQLが内部データ構造、ファイル記述子、データディクショナリなどを維持する必要があります。
実際の運用上の影響もあります。新しいユーザーがサインアップするたびに新しいテーブルを作成する必要があるシステムを本当に作成しますか?
代わりに、MySQLパーティショニング を使用することをお勧めします。 。
テーブルを分割する例を次に示します。
CREATE TABLE statistics (
id INT AUTO_INCREMENT NOT NULL,
user_id INT NOT NULL,
PRIMARY KEY (id, user_id)
) PARTITION BY HASH(user_id) PARTITIONS 101;
これにより、1つの論理テーブルを定義すると同時に、テーブルを多くの物理テーブルに分割して、パーティションキーの特定の値を照会するときにアクセスを高速化できるという利点があります。
たとえば、例のようなクエリを実行すると、MySQLは特定のuser_idを含む正しいパーティションにのみアクセスします。
mysql> EXPLAIN PARTITIONS SELECT * FROM statistics WHERE user_id = 1\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: statistics
partitions: p1 <--- this shows it touches only one partition
type: index
possible_keys: NULL
key: PRIMARY
key_len: 8
ref: NULL
rows: 2
Extra: Using where; Using index
パーティション化のHASH方式は、整数パーティションキーのモジュラスによって行がパーティションに配置されることを意味します。これは、多くのuser_idが同じパーティションにマップされることを意味しますが、各パーティションには平均で1 / N分の1の行しかありません(Nはパーティションの数です)。また、一定数のパーティションを使用してテーブルを定義するため、新しいユーザーを取得するたびにテーブルを拡張する必要はありません。
1024(またはMySQL 5.6では8192)までの任意の数のパーティションを選択できますが、それ以上になるとパフォーマンスの問題が報告される人もいます。
素数のパーティションを使用することをお勧めします。 user_id値がパターンに従っている場合(偶数のみを使用する場合など)、素数のパーティションを使用すると、データをより均等に分散するのに役立ちます。
コメントで質問を再確認してください:
HASHパーティショニングの場合、上記の例で示したように101個のパーティションを使用すると、特定のパーティションには平均して行の約1%が含まれます。統計テーブルには3000万行あるとおっしゃいましたが、このパーティションを使用すると、パーティションあたりの行数は30万行になります。これは、MySQLが読み通すのがはるかに簡単です。インデックスも使用できます(使用する必要があります)。各パーティションには独自のインデックスがあり、パーティション化されていないテーブル全体のインデックスの1%の大きさになります。
したがって、適切なパーティション数をどのように決定できるかについての答えは、テーブル全体の大きさ、およびパーティションの平均サイズをどのくらいにするかということです。
HASHパーティショニングを使用する場合、必ずしもパーティションの数を増やす必要はありません。最終的には合計300億行になる可能性がありますが、データ量が桁違いに増えると、とにかく新しいアーキテクチャが必要になることがわかりました。データがこれほど大きくなる場合は、おそらくシャーディングが必要です。 複数のサーバーにまたがって、複数のテーブルに分割します。
そうは言っても、ALTER TABLEを使用してテーブルを再パーティション化できます:
ALTER TABLE statistics PARTITION BY HASH(user_id) PARTITIONS 401;
これは(ほとんどのALTER TABLEの変更と同様に)テーブルを再構築する必要があるため、しばらく時間がかかると予想されます。
パーティション内のデータとインデックスのサイズを監視することをお勧めします:
SELECT table_schema, table_name, table_rows, data_length, index_length
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE partition_method IS NOT NULL;
他のテーブルと同様に、アクティブなインデックスの合計サイズをバッファプールに収める必要があります。これは、MySQLがSELECTクエリ中にインデックスの一部をバッファプールにスワップインおよびスワップアウトする必要がある場合、パフォーマンスが低下するためです。
RANGEまたはLISTパーティション化を使用する場合、パーティションの追加、削除、マージ、および分割がはるかに一般的です。 http://dev.mysqlを参照してください。 com / doc / refman / 5.6 / en / partitioning-management-range-list.html
パーティショニングに関するマニュアルセクション を読むことをお勧めします。 、また、この素晴らしいプレゼンテーションをチェックしてください: Boost Performance MySQL5.1パーティションを使用する場合 。