多くのSELECT / INSERT / UPDATE / DELETEでのMySQLの高パフォーマンス


9

私は、すべてのユーザーが10〜300秒間レコードをテーブルに取得するモジュールを作成しています。

時間切れになると、レコードが削除されます。ケースは:多くのユーザーが存在し、レコードは実際に頻繁に変更されます-これはこのテーブルのアプリケーションのパフォーマンスにどのように影響しますか?レコードは非常に頻繁に変更されるため、mysqlはそれで問題ないのでしょうか?インデックスが行き来するように、この特定のテーブルのデータは200回/秒のように変化します。多分私はこの種の仕事のために悪い解決策を選んでいます。助言がありますか ?

ありがとうございました!


2
memcacheにデータを保存し、数秒ごとに1つのトランザクションでデータをフラッシュしようとしましたか?

3
「この特定のテーブルでは200回/秒のようなデータ変更」このデータは、このデータはメモリに保持される必要があることを示しています。存続する必要のある存続期間は短いので、おそらくディスクに移動すべきではありませんか?

インデックスは出入りしますか?インデックスを頻繁に作成および削除する必要がある理由は考えられません。
バリーブラウン

回答:


3

考慮しなければならないことの1つは、MySQLがその主要なストレージエンジン(InnoDBMyISAM)にバッファーをどのように使用するかです。

メモリにキャッシュされるものは、これらのストレージエンジン間で大きく異なります。

InnoDBはデータとインデックスページの両方をキャッシュします。これらは、innodb_buffer_pool_sizeによってサイズが設定されたInnoDBバッファープールにロードされます

MyISAMテーブルにはインデックス・ページだけをキャッシュし、それらがによって大きさでキーキャッシュ(キーバッファ)にロードされているkey_buffer_sizeは

InnoDBバッファープールとMyISAMキーキャッシュのサイズを正しく設定するには、information_schema.tablesを使用して、ディスク上で占有されているデータとインデックスのサイズを取得する必要があります。

保持しているデータの量と許容時間に応じて、次のようにキャッシュをウォームできます。

すべてのテーブルTableT

  • 各インデックスNDXに移動
  • 各インデックスNDX
    • NDXのすべての列に対して SELECTを実行します。少なくとも1つの列がTableTからTableTでインデックス付けされていません

これにより、すべてのデータとインデックスページが少なくとも1回読み取られることが保証されます。彼らはキャッシュに座ります。この概念は、一部および原則として、Perconaによって実践されています。Perconaはこの概念をmk-slave-prefetchに組み込みました。このプログラムが行うことは

  • スレーブ内のSQLを処理するスレーブの前にスレーブのリレーログを読み取る
  • リレーログからSQLステートメントを取得し、インデックスを選択するためのガイドとしてWHERE、GROUP BY、およびORDER BY句を使用してSELECTに変換します。
  • 変換されたSQLからのSELECTステートメントを実行する

これにより、スレーブはSQLを迅速に処理するためにスレーブが必要とするデータの99.99%を保持することになります。これにより、手動でスレーブにフェイルオーバーし、マスターに昇格した場合に、スレーブが準備されます。キャッシュは、フェイルオーバーしたマスターと同じものである必要があります。

結論

INSERT、UPDATE、DELETEの負荷が高い環境で使用できるキャッシュの準備が整っていて、意欲的であり、それを実現できることは何にも勝るものです。

試してみる !!!

警告

memcachedなどの製品の誕生により、MySQLの適切なチューニングを実行する必要がなくなった製品もあります。確かに、開発者がmemcachedをすぐに目にしたように、多くのサイトは、データのキャッシュ動作を制御することによって提供されるデータ検索の向上から恩恵を受けています。他の多くのサイトは、ストレージエンジンを切り替えるか、MySQLを正しく構成するだけで、同じパフォーマンス上の利点を実現しています。データベースをあきらめて、それをリポジトリとして厳密に使用する前に、データベースを最大限に活用してください。デューデリジェンスをたどると、MySQLがあなたのために何をするのか、うれしい驚きがあるかもしれません。


5

それが悪い解決策であるならば、多くのものに依存するでしょう。このデータは永続的である必要がありますか?それ以外の場合は、このデータをメモリに保持するだけのソリューションの方が効果的です。

「多くのユーザー」は実際には誰の助けにもなりません。「たくさん」が数百を意味する場合、MySQLはおそらく問題ありません。(ただし、データベースが他に何を処理する必要があるかによって異なります。おそらく数千も動作するはずです。)

結局のところ、それらのレコードを数秒から数分後に保持または削除するように書き込んだ場合、それはそれほど重要ではありません。削除すると、1つの操作から2つの操作が実行されます。また、MySQLは非常に大量のレコードの作成と削除を確実に処理できます。単純なインデックスを使用して、削除するレコードを再度検索してください。

しかし、実際の数とデータベースサーバーが使用するハードウェアに関する情報がないと、正確に答えることはできません。

最良のことは、実際の処理を行わなくても得られると思われる負荷の量を単にシミュレートし、サーバーに対して大量のレコードをドロップし、それらを削除し、同じ速度でいくつかのクエリを実行する小さなアプリケーションを書くことですプログラムの残りの部分が生成されます。サーバーを見て、何らかの影響があるかどうかを確認してください。

確かではありませんが、メモリ内のテーブルを完全にキャッシュできるようにするMySQLの設定オプションがあります。多くの状況でとにかくこれを行うので、ほとんど変更する必要はありません。しかし、非常に大量のユーザーとレコードについて話す場合は、いくつかのパラメーターを調整して、特別なニーズに合わせてキャッシュを最適化することができます。


4
+1は、データをメモリに保持するソリューションを提案します。

3

ここにクレイジーなアイデアがあります。これには仮定が含まれ、常に推奨されるプラクティスではありません(キーの更新など)-これを提案することで多くの否定的な点が得られますが、ここではそれが行われます...

非常に大量の行と大量の削除があると仮定すると、テーブルに2つのパーティションを作成することにより、削除のパフォーマンスを向上させることができます。パーティションは、キーの最初の桁によって異なります。例:

キー値1123234441はアクティブな行用であり、キー値:9123234441は非アクティブな行用です(この例の最初の桁は次のように使用されます:1 =アクティブ、9 =非アクティブ)。

ユーザーが行を削除すると、物理的に行を削除するのではなく、キーを更新します(Ouch!)。これにより、行が非アクティブな行パーティションに自動的に移動します。

もちろん、アクティブパーティションからのみデータを読み取るように選択を制限する必要があります。ここでクールなのは、非アクティブな行パーティションの削除が非常に速いことです。

前に述べたように、これはテーブルが1つしかない場合に機能します。私はこれをテストしていないので、これは理論上のアプローチですが、パーティションのドロップの速度を経験しており、驚くほど高速です。

選択を強化するには、適切なインデックス付けを使用し、挿入を強化して、行のサイズとインデックスの数を最小限に抑えます(このステートメントは非常に一般的です...)

リファレンスについては、http//dev.mysql.com/doc/refman/5.1/en/partitioning-types.htmlを参照してください 。


2
これがこの特定の問題に対して理にかなっているのかどうかはわかりません(私の推測では、mysqlがすべてをキャッシュし、ほとんどの場合、これらのレコードにはディスクが表示されません)。しかし、+ 1は、今まで知らなかった興味深い最適化手法を指摘するためのものです。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.