web-dev-qa-db-ja.com

InnoDBエンジンで挿入遅延を使用し、挿入ステートメントの接続を減らす方法は?

多くのデータベース書き込み、約70%の挿入、30%の読み取りを含むアプリケーションに取り組んでいます。この比率には、1回の読み取りと1回の書き込みと見なす更新も含まれます。 insertステートメントを使用して、複数のクライアントが以下のinsertステートメントを介してデータベースにデータを挿入します。

$mysqli->prepare("INSERT INTO `track` (user, uniq_name, ad_name, ad_delay_time ) values (?, ?, ?, ?)");

問題は、insert_delayを使用するか、またはmysqli_multi_queryメカニズムを使用するかです。ステートメントはサーバーで最大100%のCPUを使用します。データベースでInnoDBエンジンを使用しているため、挿入の遅延は不可能です。サーバーへの挿入は〜36k/hrで、99.89%が読み取られます。また、selectステートメントを使用しています 単一のクエリでデータを7回取得 、このクエリの実行には150秒かかります。このタスクにはどのようなテクニックやメカニズムを使用できますか?サーバーのメモリは2 GBですが、メモリを拡張する必要がありますか?この問題を見てください、どんな提案も私に感謝します。

テーブルの構造:

+-----------------+--------------+------+-----+-------------------+----------------+
| Field           | Type         | Null | Key | Default           | Extra          |
+-----------------+--------------+------+-----+-------------------+----------------+
| id              | int(11)      | NO   | PRI | NULL              | auto_increment |
| user            | varchar(100) | NO   |     | NULL              |                |
| uniq_name       | varchar(200) | NO   |     | NULL              |                |
| ad_name         | varchar(200) | NO   |     | NULL              |                |
| ad_delay_time   | int(11)      | NO   |     | NULL              |                |
| track_time      | timestamp    | NO   | MUL | CURRENT_TIMESTAMP |                |
+-----------------+--------------+------+-----+-------------------+----------------+

私のデータベースには現在のステータスがあり、41kの挿入(書き込み)を示しています。これは私のデータベースでは非常に遅いです。

database status

10
Shashank

書き込みよりも読み取りが多いので、以下をお勧めします

InnoDBの適切なチューニングが鍵となります

バッファープール(サイズ innodb_buffer_pool_size

InnoDBはINSERT DELAYED をサポートしていないため、大きなInnoDBバッファープールを使用することがINSERT DELAYEDに到達できる最も近いものです。すべてのDML(INSERT、UPDATE、およびDELETE)は、InnoDBバッファープールにキャッシュされます。書き込みのトランザクション情報は、すぐにREDOログ(ib_logfile0、ib_logfile1)に書き込まれます。バッファープールに送信された書き込みは、ibdata1(セカンダリインデックスのInsertBuffer、二重書き込みバッファー)を介してメモリからディスクに定期的にフラッシュされます。バッファープールが大きいほど、キャッシュできるINSERTの量が多くなります。 RAMが8GB以上のシステムでは、RAMとしてinnodb_buffer_pool_sizeとして75〜80%を使用します。RAMが非常に少ないシステムでは、25%(OSに対応するため)。

警告: innodb_doublewrite を0に設定すると、書き込みをさらに高速化できますが、データの整合性のリスクがあります。 innodb_flush_method をO_DIRECTに設定して、InnoDBをOSにキャッシュしないようにして、速度を上げることもできます。

再実行ログ(サイズ別 innodb_log_file_size

デフォルトでは、REDOログの名前はib_logfile0およびib_logfile1で、それぞれ5MBになります。サイズはinnodb_buffer_pool_sizeの25%にする必要があります。 REDOログがすでに存在する場合は、my.cnfに新しい設定を追加し、mysqlをシャットダウンして削除し、mysql を再起動します。

ログバッファー(サイズ: innodb_log_buffer_size

ログバッファは、変更をREDOログにフラッシュする前にRAMで保持します。デフォルトは8Mです。ログバッファが大きいほど、ディスクI/Oは少なくなります。非常に大きなトランザクションには注意してください。これにより、COMMITがミリ秒単位で遅くなる場合があります。

複数のCPUへのアクセス

MySQL 5.5およびMySQL 5.1 InnoDBプラグインには、InnoDBストレージエンジンが複数のCPUにアクセスするための設定があります。設定する必要があるオプションは次のとおりです。

  • innodb_thread_concurrency InnoDBが開いたままにできる並行スレッドの数の上限を設定します。通常、(2 X CPU数)+ディスク数に設定することをお勧めします。昨年、私はPercona NYC Conferenceから直接、それを0に設定して、実行している環境に最適なスレッド数を見つけるようにInnoDBストレージエンジンに警告する必要があることを学びました。
  • innodb_concurrency_tickets は、問題のない並行処理チェックをバイパスできるスレッドの数を設定します。この制限に達すると、スレッドの同時実行チェックが再び標準になります。
  • innodb_commit_concurrency は、コミットできる同時トランザクションの数を設定します。デフォルトは0なので、これを設定しないと、任意の数のトランザクションを同時にコミットできます。
  • innodb_thread_sleep_delay は、InnoDBキューに再び入る前にInnoDBスレッドが休止できるミリ秒数を設定します。デフォルトは10000(10秒)です。
  • innodb_read_io_threads (これを3000に設定)および innodb_write_io_threads (これを7000に設定)(両方ともMySQL 5.1.38以降)は、指定された数のスレッドを読み取りと書き込みに割り当てます。デフォルトは4で、最大値は64です。これらを64に設定します。また、 innodb_io_capacity を10000に設定します。

MySQL 5.5にアップグレード

MySQL 5.0を使用している場合は、MySQL 5.5にアップグレードします。 MySQL 5.1.37以前を使用している場合は、MySQL 5.5にアップグレードします。 MySQL 5.1.38以降を使用していて、MySQL 5.1のままにする場合は、InnoDBプラグインをインストールします。これにより、InnoDBのすべてのCPUを利用できます。

11
RolandoMySQLDBA

INT(2)は引き続き4バイトを使用します-おそらくあなたはTINYINT UNSIGNEDを意味していましたか?

Setnoにはいくつの異なる値がありますか?小さい場合、KEY(setno)は使用されません。 INSERTはそのインデックスを更新する必要があります。 KEYを削除すると、INSERTの速度が上がります。

CHAR(10)-flagは常に10文字ですか?そしてutf8では?おそらくフラグVARCHAR(10)CHARACTER SET asciiを使用できます

挿入をバッチ処理します-一度に100は10倍の速度で実行されます。 (100を超えると、「収益の減少」に陥ります。)

自動コミットの価値は何ですか?各INSERTをBEGIN ... COMMITでラップしていますか? innodb_flush_log_at_trx_commitの値は何ですか?

2
Rick James

キューを設定します。アプリケーションは、一度に1行ずつキューに書き込み、最後に挿入してから経過した時間の行数に基づいて、行を取り出してデータベースにバッチで挿入します。

一度に10,000個のインサートをバッチ処理するのが最も高速であるので、スイートスポットを見つけるためにテストする必要があります。

独自のシンプルなキューシステムを作成するか、既存のキューシステムを使用できます。次にいくつかの例を示します: HornetQ および File :: Queue 。ここに他のいくつかの良いオプションをリストするSEへの投稿があります: Perl、php、pythonのメッセージキュー

1
dabest1