スレッドで処理資源を制限する
課題説明
今って、大きく課題にアサインしてもらった。現状は、データ数が多すぎるので、そして、データ抽出したあとにそのロジックコードも長すぎる、ざっくりみると、20000行以上である。中で別システム連携であるのみにならず、DBデータの再抽出も多い。
テストの最小単位で3万件のデータをダウンロードに試してましたが、ローカルの開発環境で全然無理です。15分ほどにかかったあと、すぐダンしてしまった。
プロジェクトリーダーは「エラーになる行を見て、解決してください。」と言った
僕にとって日本では技術のことが知らないリーダーが多いです、実際はこんなに簡単に解決ではなく、性能問題は開発の段階に考えられるものと思うですが、仕様不備やスケジュールを合わせるため、開発段階にもややこしかったかもしれない
ほぼ、現状を把握から解決まで二週間を経った、問題は以下になる
- loopの中にLoopが多すぎる
- 全件数を抽出した、未出力のデータって長期にメモリーを占用する
- 全データ処理後一瞬にファイルを出力する、400MBくらい
- SQL:where id in(...2000個以上のストリング...)
- 本番環境のメモリーは4GBがあるのに、2GBだけ使われてる
実現目標
100000件以上のデータがダウンロードできるように修正
アーキテクチャはこうになる
解決案
一番目の解決案はリストタイプをMapタイプに修正すればOKです。
二番目は全件数を抽出したので、回数による処理件数を制御すると僕は考えてます。リーダーさんは、「処理件数」だけで制御いけないかという質問を頂きました。
1人は「500件」、10人同時にダウンロードすれば並列件数が5000件です。30人なら、15000件。
以上の問題をもって、実験したが、5000件以内は別の機能に性能影響が最も小さい。
三番目の解決案は、一行ずつファイルに出力する、処理後にCSVの該当オブジェクトをNullにして、JVMがメモリー資源を自動的に開放できる
四番目は根拠の問題はMySQLのインデックスに走らなかったです、INの結合句は2000以上であるので。これに対すて、新しくテーブルを作成しました、毎回処理の回数データは「insert into new_table_name(申込ID) select * from old_table_data」テーブルにインサートする、別のSQL分抽出のデータはLeft Joinの結合句を追加していい、そして、プログラムに経由しなく、SQL分の組み立てる時間もなかった。当該回数処理する後、テーブルのデータを抹消する。
五番目は、インフラチームに触れないため、避けるしかない
最後
15 万件のテストデータは一人10分ほどかかるという実績を出てきました。
同時に5人ダウンロードできる。同時の処理件数が「5000件」、もちろん、すべてプロパティファイルに配置できる
全100000件/一回処理1000件=100回数
6人同時にダウンロード場合は、一人は列に並ぶ、スレッドプールが空いたら、スレッド処理を行う。
评论
发表评论