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


14

私は既存のプロジェクトで作業を開始し、前の開発者は、テーブルを、スキーマは同じでもデータが異なる10個の個別のテーブルに分割していました。

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

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

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

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

だから、私の質問は、これが実行可能な解決策であるかどうか、それがどんな状況でも良い方法であるかどうかです。私の理論は、それらを組み合わせるようにプッシュすることですUNION。主な欠点は、すべてのアプリケーションコードを変更することと、長期的に見ても価値があるかどうかです。

回答:


16

私は誰もがこれを過度に複雑にしていると思います。ここで重要な点は次のとおりです。

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

これは、ケーキのハンドルへのRDBMSのため。 1つのテーブルに移動して、適切にインデックスを作成し、解決済みの問題と見なします。

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


3

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

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

パーティション分割には多くの利点があります。ただし、実際のデータセット、アクセスパターン、およびインデックスの作成方法によって異なります。また、以下のコメントは、古いmysqlマージテーブルではなく、mysql 5+パーティショニングのコンテキストにあることに留意してください。ただし、パーティションの観点から説明されることもあります。

いくつかの例:

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

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

必要なパーティショニングがアプリケーション固有であり、そのロジックをアプリケーション層に置く方が適している状況を想像できます。ただし、ストレートモジュラス10の記述を考えると、これはそのような場合には見えません。

編集

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


3

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

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

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

パーティションごとのハッシュ(ネイティブ実装)もお勧めしません。一度に各パーティションを並列検索するために使用できると便利だと思います(MySQLではできません)。複数のパーティションにまたがって検索する必要がある場合、多くの場合、説明したスキームははるかに遅くなります。

[1]ただし、他の一部のパーティショニングタイプでは、独自のパーティショニングを展開するのが理にかなっています。MySQLは、パーティションキーを主キーとすべての一意のインデックスの一部にすることを強制します。


2

質問への回答:

これが実行可能なソリューションであるかどうか

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

質問への回答:

...どんな状況でもそれが良い習慣である場合

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

たとえば、Webログテーブルのふりは次の形式を取ります。

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

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

weblogs.20120301
weblogs.20120302
weblogs.20120303

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

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


0

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

質問は次のとおりです。その分割はパフォーマンスに値するのか、それともパフォーマンスに害を及ぼすのか?

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

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

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


0

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.