MySQLのINSERTおよびUPDATEのパフォーマンスを改善する方法は?


14

この質問はおそらくStackOverflowでも聞かれますが、まずはここで試してみます...

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

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

ロックに関する問題が発生している可能性がありますが、どうすればわかりますか?


dba.stackexchange.comの方が良い
Pacerier 14

回答:


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

    • 問題の原因(CPU / IO / Memory / Swap Usage)。多くのIOPがありますか?CPUがロードされていますか?読み取りIOPが多数ある場合は、おそらく十分な大きなInnoDB buffer_poolがありません。CPUがロードされている場合、適切なインデックスを使用する代わりに、クエリがテーブル全体をスキャンする可能性があります。
    • ディスク/ RAID / LVMのセットアップ。いくつかの特定のセットアップでは、LVMストライピングはディスク負荷を等化することでメリットをもたらします(ハードウェアRAIDなし、複数のLUNが接続されます)
    • IOスケジューラー:優れたハードウェアRAIDコントローラーがある場合、おそらくnoopが最適です。RedHatはいくつかのテストを行い、Oracle(および他のDB)CFQが最良の選択であると述べました。いくつかのベンチマーク(tpc-cやtpc-eなど)を実行し、ハードウェアに最適なものを選択する必要があります。
    • 優れたファイルシステム-ext3はデータベース固有のワークロードではうまく機能しません。より良いのはXFSまたはOCFS2です。再びいくつかのベンチマークが必要です。
    • システムがスワップを使用している場合、注意してください。スワップを使用すると、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に適切なインデックスがあるかどうかを確認し、必要に応じて追加します。

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

便利なリンク:


5

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

1トランザクションの損失に対処できる場合、これは書き込みパフォーマンスを大幅に改善するための素晴らしい方法です。

また、ディスクが実行していることに注意してください。余分なディスクのコストでの書き込み用のRAID 10> RAID 5。


1

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

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

一般的に、可能な限りメモリ内で処理する必要があります。クエリの最適化では、一時テーブルを回避することを意味します。インデックスの適切な適用。

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



0

InnoDBは非常に優れたエンジンです。ただし、「チューニング」に大きく依存しています。一つのことは、挿入が主キーの増加順でない場合、innoDBはMyISAMより少し長くかかる可能性があるということです。これは、より高いinnodb_buffer_pool_sizeを設定することで簡単に克服できます。私の提案は、RAM全体の60〜70%に設定することです。現在、実稼働環境でこのようなサーバーを4台実行しており、1分間に約350万行を挿入しています。すでに3テラバイト近くあります。InnoDBは、高度な同時挿入のため、である必要がありました。挿入を高速化する方法は他にもあります。そして、私はいくつかをベンチマークしました。

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