web-dev-qa-db-ja.com

MySQLのINSERTおよびUPDATEのパフォーマンスを向上させる方法は?

この質問はおそらくStackOverflowでも質問される可能性がありますが、最初にここで試してみましょう...

データベース内のINSERTおよびUPDATEステートメントのパフォーマンスが低下し、Webアプリのパフォーマンスが低下しているようです。

テーブルはInnoDBであり、アプリケーションはトランザクションを使用します。スピードアップするために簡単に調整できるものはありますか?

ロックの問題が発生していると思いますが、どうすれば確認できますか?

14
mmattax
  1. ハードウェアとOSが適切に構成および調整されているかどうかを確認します。

    • 問題の原因(CPU/IO /メモリー/スワップ使用)。 IOPはたくさんありますか? CPUはロードされていますか?読み取りIOPが多い場合は、おそらくInnoDB buffer_poolが十分にありません。 CPUがロードされている場合、クエリは適切なインデックスを使用するのではなく、フルテーブルスキャンを実行します。
    • ディスク/ RAID/LVMセットアップ。一部の特定のセットアップでは LVMストライピング は、ディスク負荷を均等化することでメリットをもたらす可能性があります(ハードウェアRAIDなし、複数のLUNが接続されています)。
    • IOスケジューラー:適切なハードウェアRAIDコントローラーがある場合は、おそらく何もしないのが最善です。 RedHatがいくつかのテストを行いました そして、彼らは、Oracle(および他のDB)にはCFQが最良の選択だと述べました。いくつかのベンチマーク(tpc-cやtpc-eなど)を実行して、ハードウェアに最適なものを選択する必要があります。
    • 適切なファイルシステム-データベース固有のワークロードではext3はうまく機能しません。 XFSまたはOCFS2のほうが優れています。再びいくつかのベンチマークが必要です。
    • システムがスワップを使用している場合は、注意してください。 swapを使用すると、mysqlのパフォーマンスが低下します
  2. MySQL/InnoDBインスタンスが適切に調整されているかどうかを確認します。

    • バッファプールサイズ-メモリ内のキャッシュデータページ
    • innodb_flush_method = O_DIRECT-二重の回避IOバッファリング
    • innoDBログファイルのサイズを増やす-書き込みが多いワークロードの場合、これによりパフォーマンスが向上する可能性があります。ただし、覚えておいてください。ログファイルのサイズが大きいほど、クラッシュからの復旧時間が長くなります。時々時々!!!
    • innodb_flush_log_at_trx_commit = 0または2-ACIDに関心がなく、最後の1〜2秒のトランザクションが失われる可能性がある場合。
    • key_buffer_size-MyISAMにとって非常に重要ですが、ディスクの一時テーブルに使用されます。
    • INNODB STATUS に注意してください
  3. ワークロードを分析します-すべてのクエリをスロークエリログにキャッチし、mk-query-digestを実行します。 tcpdumpおよびmaatkit を使用してすべてのクエリをキャッチできます。
    • サーバー時間のほとんどを占めるクエリは何ですか?
    • 一時テーブル、特に大きな一時テーブルは作成されますか?
    • 学習、説明の使用方法
    • アプリケーションはトランザクションを使用していますか? autocommit = 1(デフォルトはMySQL)でクエリを実行すると、すべての挿入/更新クエリが新しいトランザクションを開始し、オーバーヘッドが発生します。可能であれば、自動コミットを無効にし(python MySQLドライバーの自動コミットはデフォルトで無効になっています)、すべての変更が完了した後で手動でコミットを実行することをお勧めします。
    • アプリケーションはループ内の同じテーブルに一連の挿入を行いますか? _Load data infile_コマンドは、一連の挿入に対してはるかに高速です。
    • 注意:select count(*) from table;は、myisamよりもinnodbの方がはるかに低速です。
    • どのタイプのINSERT/UPDATEクエリがサーバー時間の大部分を占めますか?それらをどのように最適化できますか?
    • DBに適切なインデックスがあるかどうかを確認し、必要に応じて追加します。

私たちの環境では、あるタイプの更新クエリが遅いという状況がありました。バッチジョブを完了するための推定時間は2日でした!!! slowqueryログを分析した後、このタイプの更新クエリが完了するまでに4秒かかることがわかりました。クエリは次のようになりました:_update table1 set field1=value1 where table1.field2=xx table2.field3=yy and table2.field4=zz_。更新クエリを選択クエリに変換し、その選択クエリで説明を実行した後、このタイプのクエリはインデックスを使用しません。適切なインデックスを作成した後、更新クエリの実行時間をミリ秒に減らし、ジョブ全体を2時間未満で完了しました。

いくつかの便利なリンク:

25
sumar

デフォルトのinnoDB構成では、トランザクションをディスクに書き込んでフラッシュできる速度に制限されます。 ACIDの損失に対処できる場合は、innodb_flush_log_at_trx_commitを試してください。約1秒ごとにログをディスクに書き込んでフラッシュするには、0に設定します。コミットごとに書き込みおよびフラッシュするには、1(デフォルト)に設定します。 2に設定すると、コミットのたびにログファイルに書き込まれますが、フラッシュは1秒に1回だけです。

1トランザクションの損失に対処できる場合、これは書き込みパフォーマンスを大幅に向上させる優れた方法です。

また、ディスクの動作にも注意してください。 RAID 10> RAID 5は、追加のディスクを犠牲にして書き込みを行います。

5
tomchuk

Innodbモニターをオンにすると、ロックとデッドロックの原因を特定するのに役立ちます。

SHOW ENGINE INNODB STATUS and InnoDB Monitors

1
Martin

ロックの問題は、show full processlist;の接続ステータスに例示されます

my.cnfおよびMySQLのドキュメントを読みます。設定オプションは非常によく文書化されています。

一般的に言えば、メモリ内でできるだけ多くのデータを処理する必要があります。クエリの最適化では、これは一時テーブルを回避することを意味します。インデックスの適切な適用。

チューニングは、使用するデータベースエンジンとアプリケーションアーキテクチャに固有になります。既存のインターネット検索にはかなりのリソースがあります。

1
Warner

自動コミットを無効にしてJavaで変更をコミットするだけで、WebアプリケーションのMySQLで挿入と更新のパフォーマンスの問題を解決する方法mysqlのドキュメントで提案されています。

MySQLドキュメント

0
Jatinder

InnoDBはかなり良いエンジンです。ただし、これは「調整」されることに大きく依存しています。 1つのことは、挿入が主キーの増加順になっていない場合、innoDBはMyISAMよりも少し長くかかることがあります。これは、より高いinnodb_buffer_pool_sizeを設定することで簡単に克服できます。私の提案は、RAM全体の60〜70%に設定することです。現在、このようなサーバーを4つ運用し、1分あたり約350万行を挿入しています。すでに3テラバイト近くあります。 InnoDBは、非常に並行した挿入のため、でなければなりませんでした。インサートを高速化する方法は他にもあります。そして、私はいくつかをベンチマークしました。

0
Ajay Divakaran