並列非同期で DB レコードの Update を走らせる際のチャンク分割数は、どれぐらいが最適なのか?
(前提)まずは、DBの設定を確認する
最適なチャンク分割数を決めるためには、
まずは、DB の max connections(最大接続数)とmax allowed allowed packet(最大許可パケットサイズ)を確認する必要があります👀
max_connectionsとmax_allowed_packetの設定値
-
max_connections
は、MySQLサーバーが同時に許可する最大のクライアント接続数を指定する設定です。- デフォルト値は151で、これは同時に151のクライアントが接続可能であることを意味します。
- この値を超える接続要求があると、新たな接続は拒否され、エラーが返されます。
-
max_allowed_packet
は、MySQLサーバーが1回の通信で受け入れることができる最大のパケットサイズ(バイト単位)を指定する設定です。- この設定は、特に大きなBLOBやTEXTデータを扱う際に重要となります。
- デフォルト値は4MB(4,194,304バイト)
- local DB 設定では約47.6MB(49,999,872バイト)に設定されている。
- この値を適切に設定しないと、大きなデータの挿入や取得時にエラーが発生する可能性があります。
MySQLの場合の確認方法はこちら💁
mysql> SHOW VARIABLES LIKE 'max_connections';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 151 |
+-----------------+-------+
1 row in set (0.07 sec)
mysql> SHOW VARIABLES LIKE 'max_allowed_packet';
+--------------------+----------+
| Variable_name | Value |
+--------------------+----------+
| max_allowed_packet | 49999872 |
+--------------------+----------+
1 row in set (0.00 sec)
並列非同期でデータベースのレコードを更新する際の考慮事項など整理する
並列非同期でデータベースのレコードを更新する際のチャンク分割数を最適化するには、以下の要素を考慮する必要があります。
1. データベースの同時接続数の制限
データベースは同時に処理できる接続数に制限があります。
チャンクサイズが大きすぎると、データベースに過負荷がかかり、パフォーマンスの低下やタイムアウトが発生する可能性があります。
2. ネットワークの帯域幅とレイテンシ
大量の並列リクエストはネットワーク資源を消費します。
帯域幅が十分でない場合、パフォーマンスが低下する可能性があります。
3. アプリケーションのリソース
CPUやメモリなど、アプリケーションが利用できるリソースも考慮に入れる必要があります。
過度な並列処理は、アプリケーション自身のパフォーマンスに影響を与えることがあります。
4. データベースの種類と設定:
一部のデータベースは並列処理に最適化されており、高い同時接続数を処理できます。
データベースのドキュメントや設定を確認して、最適な並列数を判断する必要があります。
おすすめのアプローチ
-
段階的なテストとモニタリング:
- まずは現在のチャンクサイズ(10)でベースラインのパフォーマンスを測定します。その後、チャンクサイズを徐々に増やし(例えば、20、50、100)、それぞれのパフォーマンスとシステムへの影響をモニタリングします。
-
ベンチマークの実施:
- 各チャンクサイズでの処理時間、エラー率、データベースの負荷などを比較します。
- 最適なチャンクサイズは、最も効率的に処理を完了し、エラーや過負荷を引き起こさないサイズです。
-
データベースの設定確認:
- データベースの最大接続数やスレッドプールのサイズなどを確認し、必要に応じて調整します。
-
エラーハンドリングとリトライロジック:
- 並列処理中にエラーが発生した場合に備えて、適切なエラーハンドリングとリトライ機能を実装します。
まとめ
チャンクサイズを一概に「これが最適」と言い切ることは難しく、環境や条件によって最適な値は異なります。
しかし、一般的には20から50程度から始めてみるのが良いでしょう。
重要なのは、システムのパフォーマンスをモニタリングしながら、最適なチャンクサイズを見つけることです。
チャンク分割数の最適化
DB の設定が次のような場合の並列非同期で DB レコードの Update を走らせる際のチャンク分割数を考える🤔
bash
mysql> SHOW VARIABLES LIKE 'max_connections';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 1000 |
+-----------------+-------+
1 row in set (0.07 sec)
mysql> SHOW VARIABLES LIKE 'max_allowed_packet';
+--------------------+----------+
| Variable_name | Value |
+--------------------+----------+
| max_allowed_packet | 49999872 |
+--------------------+----------+
1 row in set (0.00 sec)
データベースの設定で max_connections
が 1000 に設定されている場合、理論的には同時に1000の接続を処理できることになります。
しかし、実際には他のアプリケーションやプロセスもデータベースに接続している可能性があるため、全ての接続を使い切るのは避けるべきです。
おすすめのチャンクサイズ
-
100から200の範囲でチャンクサイズを設定してみることをおすすめします。
- この範囲はデータベースの負荷を適度に高めつつ、過負荷を避けるのに適しています。
- ただし、同時接続数が多いアプリの場合は、もっとチャンクサイズを少なくする方がいいでしょう。
- 10〜50ぐらいのレンジで決める。
理由と考慮点
-
データベースの安定性:
max_connections
の70~80%を超えると、接続待ちが発生したり、データベースの応答性が低下する可能性があります。 -
他の接続との競合を避ける: アプリケーション内の他の部分や、他のサービスがデータベースを使用している場合、それらの接続を妨げないようにします。
-
リソースの有効活用: チャンクサイズを現在の10から増やすことで、処理時間を短縮できる可能性があります。ただし、適切な範囲内で調整する必要があります。
モニタリングとテストの重要性:
-
段階的な増加: まずはチャンクサイズを50に増やし、システムのパフォーマンスを観察します。その後、問題がなければ100、150と徐々に増やしていきます。
-
パフォーマンスメトリクスの収集: データベースのCPU使用率、メモリ使用量、ディスクI/O、接続数などをモニタリングします。
-
エラーレートの監視: タイムアウトや接続エラーが発生していないか確認します。
実装上の注意点:
-
コネクションプールの利用: データベース接続を効率的に管理するために、コネクションプールを使用します。これにより、接続のオーバーヘッドを削減できます。
-
エラーハンドリング: 接続エラーやタイムアウトが発生した場合に備えて、リトライロジックを実装します。
-
リソースの解放: 非同期処理が完了した後、不要になったリソースや接続を適切に解放します。
max_allowed_packet
の考慮
-
データサイズの確認:
max_allowed_packet
が約50MBに設定されています。個々の更新クエリがこのサイズを超えないことを確認してください。大きなデータを扱う場合は、パケットサイズを調整する必要があります。
まとめ:
チャンクサイズを 100から200 に設定し、システムのパフォーマンスをモニタリングしながら調整することをおすすめします。
重要なのは、データベースとアプリケーションの安定性を維持しつつ、効率的に処理を完了することです。
パフォーマンスとデータベースの負荷を観察してください。必要に応じてチャンクサイズを調整し、最適な値を見つけてください。
JavaScript/TypeScriptでデータのチャンク分割をするならlodash.chunkがおすすめ