大容量データを扱う
どもども、ジャナイホーです。
みなさま、数万行、数十万行のデータを扱う機会もあるかと思います。
そんなとき、
思ったようなパフォーマンスが出ない、
とか、
メモリ不足が発生して、プロセスが落ちてしまった、
とか、苦労されていることも多いことでしょう。
そこで今回は、大容量のデータを扱う際のTipsをご紹介します。
コレクション(Collection)のあつかい
大容量のデータは、Blue Prism上では、Collection(コレクション)に入れてから、コレクションの値からアプリケーションに対して登録したり、など、数々の操作をすると思います。
コレクションの中にコレクションを入れたり、超長いテキストデータを含めることもできますので、すごく便利な入れ物なのですが、その反面、最大行数や最大サイズは定義できないため、作り手に言われるがまま、無尽蔵にメモリを消費していきます。
なので、大量のデータを一度にどーんとコレクションに入れて扱うことは注意が必要です。
気を付けないと、パソコンやOSで扱えるメモリには限りがあるので、メモリ不足でハングしたり、落ちたりして、大変なことになってしまいます。(ここで言う「メモリ等を消費するパソコン」は、Blue Prismの場合は「ランタイムリソース」になります。サーバではありません。)
なので、大量の、数万件、数十万件レベルであれば、例えば、1万件ごとなどの細かい単位に分割して処理するように実装するのがおススメです。
1万件ごとに、読み込み
↓
登録など画面操作処理
↓
コレクションのクリア(Remove All Rowsなど)
↓
次の1万件の読み込みを行う
→ この一連の流れを繰り返すようにする
といった実装方法などです。
パフォーマンスに懸念があるときは、本当に、
「どうしても全件データを纏めて処理しなければいけないのか?」
「細かな単位に分割して、小分けで処理できないものか?」
要件・仕様の再検討から始めてみることをおススメします。
巨大サイズのコレクションのTips
で、コレクションを使って大量データを扱う際には、こんなことに気を付けてみて下さい、的なものを挙げてみます。
巨大サイズのコレクションは使わない
(そもそも大容量を一度に全部ロードしない。分割してロードし、処理し、を繰り返す)巨大サイズのコレクションのソートやフィルタリングをしない
巨大サイズのコレクションをページ間のパラメータで渡さない
巨大サイズのコレクションは使わなくなったら、都度、即座に空にする
コレクション上の不要なカラムやレコードは早めに削除する
複数ページ間でコレクションの受け渡しを行う場合、グローバル変数としてコレクションを定義する
どうしても必要な場合は、Excelマクロなどで処理することも検討する
コレクションのループ(繰り返し)処理での各ステージのログはオフにする
GC.Collect()を実装したコードステージを実行し、.Net Framworkのメモリ開放を促す
読み込み、書き込みのスピード
大抵の場合、大きなコレクションを扱いたい場合は、Excelから読み込みたいことが多いかと思います。
Blue Prismのプロセスで大容量データを扱う為にExcelから取り込む方法は、いくつかあります。
Excel VBOの Get CSV as Collectionなどのアクションを使う
→ 一番一般的ですね。Excel VBOの他のアクションを使う
OLEDB VBOを使う
などです。
ここで、読み込み、書き込みのスピード感を下記に示します。(ある一定の条件下ですので、必ずしもみなさんの環境には適合しないかとは思いますが、ちょっとした相対評価としてのご参考まで。)
やはり胆は、上でも書きましたが、少ない単位で取り扱う、です。(ただ、あまりに小さすぎるとそれはそれで時間もかかります。メモリ消費量とパフォーマンスのバランスを見る必要がありますね。)
「Excel だと Range を指定して、読み込む、書き込む。」
「OLEDB VBOでも、WHERE句を指定出来るので、出来る限り、絞り込んで読み込む。」
1. Excel 標準VBO+コレクション
Range指定で細かく分割して繰り返し処理するパターンです。
1万件ごとに繰り返すように実装しています。読み込みは標準のMS Excel VBOの「Get Worksheet Range as Collection」を利用しました。これは読み込みは早いですが、書き込み時に利用している「Write Collection」がやたらと遅いです。これは注意ですね。
2. Excel 標準VBOのコピーペースト
すべて選択し、コピーし、別のExcelへペーストする機能をExcelのVBAで実行するものです。標準のMS Excel VBOの「Copy and Paste Worksheet Range」を利用しています。
右から左へデータをそのまま流し込むだけで良いのであれば、この方法が一番パフォーマンスが良くて、手っ取り早いです。
3. OLEDB テキストファイルとして処理
読み込みは一括(SELECT分を実行するだけ)ですが、書き込みは1件ずつINSERTの繰り返しが必要なので、ここがパフォーマンスが悪いです。
ちなみに、読み込みの際の接続文字列は、以下のようなものを指定します。
Provider=Microsoft.ACE.OLEDB.12.0;Data Source="c:\temp";Extended Properties="text;FMT=Delimited;HDR=YES;"Provider=Microsoft.ACE.OLEDB.12.0;Data Source="c:\temp";Extended Properties="text;FMT=Delimited;HDR=YES;"
で、SELECT文は、こんな感じです。
SELECT * FROM [大容量.csv]
書き込みの際の接続文字列
Provider=Microsoft.ACE.OLEDB.12.0;Data Source="c:\temp";Extended Properties="text;FMT=Delimited;HDR=YES;"
書き込むSQL文は、INSERTを使います。
INSERT INTO [大容量_YYYYMMDD_HHMMSS.csv] values ('1', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O')
これを全行、1行1行、地道に繰り返します。
4. OLEDB Excelファイルとして処理
こちらも、読み込みは一括(SELECT文を実行するだけ)ですが、書き込みは1件ずつINSERTの繰り返し、なのですが、こっちはやたら早く終わりました。ちょっとこのOLEDBの中身の仕組みに詳しくないので分からないのですが、Excelとして扱う方が早いようです。
接続文字列は以下のようになってまして、前述のテキストファイル読み込みとは少し違います。
Provider=Microsoft.ACE.OLEDB.12.0;Data Source="c:\temp\大容量.xlsx";Extended Properties="Excel 12.0 Xml;HDR=YES;"
で、SELECT文は、こんな感じです。シート名の後ろに $ マークが必要です。
SELECT * FROM [大容量$]
書き込みの際の接続文字列
Provider=Microsoft.ACE.OLEDB.12.0;Data Source="c:\temp\大容量_YYYYMMDD_HHMMSS.xlsx";Extended Properties="Excel 12.0 Xml;HDR=YES;"
書き込むSQL文は、INSERTを使います。
INSERT INTO [大容量$] values ('1', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O')
これを1行1行、地道に繰り返します。
OLEDBの使い方は、下記をご利用下さい。
Blue Prism - データ OLEDB
まとめ
巨大サイズのコレクションは使わないこと。なるべく細かい単位に分割して、逐次処理するような設計、実装にするのが望ましいです。
読み込み、書き込みの手段も、いくつかあるので、早いもの、扱いやすい(=メンテナンスしやすいもの)を利用するようにしてみて下さい。
コピペを行う処理が簡易で便利です。Write Collectionは時間がかかる場合があります。
OLE DB VBOも使ってみましょう。
※本投稿は、別ブログで掲載・公開していた内容に加筆・修正を加え再掲載しています。