web-dev-qa-db-ja.com

MySQLでのテーブルの分割。いい練習?

私は既存のプロジェクトに取り組み始め、前の開発者はテーブルを10個の別々のテーブルに分割しましたが、スキーマは同じですがデータが異なります。

テーブルは次のようになります。

[tableName_0]
[tableName_1]
[tableName_2]
[tableName_3]
[tableName_4]
[tableName_5]
[tableName_6]
[tableName_7]
[tableName_8]
[tableName_9]

主キーは整数のidフィールドです。アプリケーションは、ハッシュアルゴリズム(id mod 10)を使用して、ルックアップを行うときにアクセスするテーブルを認識します。たとえば、id = 10は[tableName_0]になります。

結合すると、テーブルにはおそらく100,000行が含まれ、成長率は比較的低くなります。

だから、私の質問は、これが実行可能な解決策であるかどうか、またはそれがどのような状況でも良い習慣であるかどうかです。私の理論では、UNIONsなどについては、それらを組み合わせてプッシュすることにより、物事がより簡単になるとしています。主な欠点は、すべてのアプリケーションコードを変更することと、長期的に見ればそれだけの価値があるかどうかです。

14
PinkGrapefruit

誰もがこれを複雑にしています。ここでのポイントは次のとおりです。

結合すると、テーブルにはおそらく100,000行が含まれ、成長率は比較的低くなります。

これは、RDBMSが処理するピースです。 1つのテーブルに移動し、適切にインデックスを付け、それを解決済みの問題と見なします。

非常に大量のデータの処理を開始するまで、「自家製」かどうかに関係なく、パーティション分割を考慮する必要はありません。数十億行以上と考えてください。

17
Nick Chammas

前の開発者があなたのために行ったことは、ハッシュによるパーティションの独自の実装を構築することです。 MySQLは文字通り、これをMySQL 5.1からネイティブにサポートしています。

http://dev.mysql.com/doc/refman/5.1/en/partitioning-hash.html

私は正当な理由を考えることができないので、ネイティブバージョンに依存するのではなく、独自のハッシュごとのパーティションを実装します[1]。スキーマ変更の実行は悪夢になります。

また、partition-by-hash(ネイティブ実装)を推奨することもほとんどありません。これを使用して各パーティションを一度に並列検索できると便利だと思います(MySQLではできません)。複数のパーティションをまたがって検索する必要がある場合、説明したスキームは、多くの場合、遅くなります。

[1]ただし、他のパーティションタイプの一部では、独自のパーティションをロールするのが理にかなっています。 MySQLでは、パーティションキーをプライマリキーとすべての一意のインデックスの一部にする必要があります。

3
Morgan Tocker

マージテーブルを使用できますが、4.xバージョンからは時代遅れになっています。アプリケーションが手動でパーティション分割されていることを考えると、a)本当に古いバージョンを実行しているか、b)元の開発者はテーブルパーティションを認識していませんでした。

つまり、5.1以降を実行している場合は、mysqlにこのパーティショニングを行わせることができます。 http://dev.mysql.com/doc/refman/5.1/en/partitioning.html を参照してください。5.5を使用している場合は、いくつかの違いがあるので、それらの特定のドキュメントを確認してください。

パーティショニングには多くの利点があります。ただし、それは実際のデータセット、アクセスパターン、およびそれをどのようにインデックス化するかによって異なります。また、私の次のコメントはmysql 5+パーティショニングのコンテキストであり、古いmysqlマージテーブルではないことに注意してください。ただし、パーティションに関して説明されることもあります。

いくつかの例:

  • 頻繁にアクセスされるルックアップキーに基づくストレートバケット(またはハッシュ)。主キーまたはその他の一意のキーで常に検索している場合、mysqlは、パーティションの数に応じて検索スペースを削減できます。ただし、1つのキーでパーティション化してから、別のキーで頻繁に検索する場合は、これが有害になる可能性があることに注意してください。キーによって検索する場合、データはパーティション化されていません。ルックアップでMORE検索を実行する必要があります(パーティションごとに1つ、率直に言って、データの場所がわかりません)。
  • 日付ごとに増加する一時的なレコードのセットがあり、前月を定期的にプルーニングした場合の状況を考慮してください。日付でパーティション化している場合は、テーブルをドロップするのと同じくらい速いパーティションをドロップすることができます。このようなテーブルを日付で整理する場合、個々の行が削除される1つ以上のDELETEクエリを発行する必要があります。これの欠点は、このシナリオで考慮した最大日付に達すると、mysqlが自動的に新しいパーティションを作成しないことです。必要に応じてパーティションを追加するには、追加のメンテナンススクリプトが必要です。
  • Myisamチェックを使用している場合、回復ははるかに高速です。 100G myisamテーブルを考えてみましょう。クラッシュしたテーブルをリカバリする場合は、少なくとも約100Gの予備のディスク容量が必要です。同じサイズの10個の異なるチャンクに分割されている場合は、10Gのスペースのみが必要です(高速リカバリのためにkey_sort_bufferメモリが少なくて済みます)。ただし、パーティションごとに反復を行う必要があります。

したがって、要約すると、テーブルをパーティション分割する一般的なアプローチには、多くの利点があります。ただし、アクセスパターンと方法を考慮せずに盲目的に適用するのは魔法の弾ではありません。

望ましいパーティション分割が非常にアプリケーション固有であり、そのロジックをアプリケーション層に配置する方が適している状況を想像できます。ただし、ストレートモジュラス10の説明では、これはそのようなケースのようには見えません。

[〜#〜]編集[〜#〜]

説明を書いているときに、テーブルが10万行であると述べたことを忘れていました。テーブルのスキーマ全体と行の平均長がないと、特定の言葉を言うのは難しいですが、一般的に、適度なハードウェアでも中程度のサイズに聞こえます。同時に、それが現在または予測可能な将来の方法で問題を引き起こしていない場合は、時間を費やしたり、変更してリスクを導入したりしないでください。

3
atxdba

質問への回答:

これが実行可能な解決策であるかどうかです

私見、これは不要なオーバーヘッドのようです。説明で明らかにされていない他の情報がない限り、単一のテーブルを適切にインデックス付けしてパーティション分割することができます。

質問への回答:

...それがどんな状況でも良い習慣なら

私見、垂直分割はコンテキストに応じて意味をなすことができます。これを見ると、通常は何らかのログ形式になっています。これをWebサーバーのログに使用していて、月ごとに分割したいとします。既存のテーブルを毎日変更する代わりに、毎日新しいテーブルを作成し、そのテーブルに行を記録することができます。

例えばWebログテーブルが次のような形式であると想定します。

datetime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
uri VARCHAR(1024),
Host VARCHAR(255),
user_agent VARCHAR(255),
etc...

ソリューションは、必要に応じてウェブログデータベースにテーブルを作成します。

weblogs.20120301
weblogs.20120302
weblogs.20120303

等.

このようにして、データは保守可能で検索可能なままです。抽出は通常の定期的なプロセスになります。古いデータに対する操作によって、継続的な操作がロックアウトされることはありません。

あなたが提示したシナリオでは、とにかく構造にロックされているので、この目的のために最適化された単一のテーブルを使用してみませんか?アルゴリズムに基づく行の格納は、大ざっぱでエラーが発生しやすいようです。

2
randomx

クエリが膨大なデータを対象とする場合、クエリ条件でデータを分割すると、パフォーマンスが著しく向上します。しかし、あなたが見てきたように、そのような分割はいくつかのプログラミング問題を引き起こします。

したがって、問題は、その分割はパフォーマンスにとって価値があるのか​​、それともパフォーマンスに悪影響を与えるのか、ということです。

複数のテーブルにまたがる複数の行をロックする必要があるトランザクションがあり、それに問題(たとえば、デッドロックやトランザクションのタイムアウト)がある場合、それらを単一のテーブルに結合し、SQLを書き直して問題を修復することができます。

テーブルを分割するかどうかを考えるとき、以前はパフォーマンスの向上とプログラミングの複雑さの間のトレードオフを考慮していました。

あなたの状況では、既存のコードの変更は、コードを保守しやすくするための長期的な解決策になる場合があります。メタプログラミングを試してみることをお勧めします。たとえば、SQLを動的に生成するには StringTemplate を使用します。既存のコードの変更が難しい場合は、メタプログラミングエンジンからSQLを生成します。

0
Mike Lue

テーブルにファイルを保存する必要がある場合、この方法論を使用すると、エクスポート、修復、復元に役立ちます。

30 Gbを超えるテーブルが10個のテーブルに分割されています。これらのテーブルにはID-BLOBのみがあり、私にとっては簡単に保持できます。そして、MyISAMを使用してINNODBバッファーを保存します。

0
Marcelo Bus