[groonga-dev,04069] Re: io_flushが大量のメモリを確保する

Back to archive index

Kouhei Sutou kou****@clear*****
2016年 7月 7日 (木) 11:48:52 JST


須藤です。

In <20160****@orega*****>
  "[groonga-dev,04067] Re: io_flushが大量のメモリを確保する" on Wed, 06 Jul 2016 10:53:14 +0900,
  高見 直輝 <takam****@orega*****> wrote:

>> 今のio_flushの実装はすべてのテーブル・カラムをフラッシュしま
>> す。このとき、まだ開いていないテーブル・カラムならそのテーブ
>> ル・カラムのファイルを開いてフラッシュします。このファイルを
>> 開いたときにリソースを確保するのでメモリー使用量が増えます。
> 
> 『開いた』というのは、PostgreSQLでSelect文を発行した場合も含まれるのでしょうか?

はい。「SELECT ... WHERE column @@ "クエリー"」のように
PGroongaのインデックスを使うSELECT文を発行したときもGroonga
のテーブル・カラムを開きます。このとき、メモリー使用量が増え
ます。

念のための補足ですが、一度開くと今後は開いたテーブル・カラム
を使いまわすので、上述のSELECT分を実行するごとにメモリー使用
量が増え続けることはありません。1回目のSELECT分で増え、それ
以降は一定です。(一時的に確保するメモリーはありますが、それ
らは処理が終わったら開放します。)

> io_flushのドキュメントを読むと、このコマンドは“Groongaデータベースへの変更量に応
> じて処理が重くなる”とあるのですが、Select文もGroongaデータベースを変更するのでしょ
> うか?

変更しません。
そのため、何度SELECT文を実行しても処理の重さは変わりません。

> また、この処理は“OSが自動的に書き出す”場合にも同様の挙動となるのでしょうか?

「この処理」は「Groongaデータベースへの変更量に応じて処理が
重くなる」の「処理」であっていますか?であれば、同様の挙動に
なります。なお、ここの「処理」は「メモリー上にだけある変更を
ディスクに書き出す」処理になります。「処理が重くなる」のはディ
スクに書き出されるデータ量が増えるとI/Oの時間が増えるからで
す。

OSが自動的に書き出す場合も、ディスクにデータを書き出すので同
様に、メモリー上にだけあるデータ量が多いほど重くなります。

> 現在、このコマンドを実行するとメモリの大量使用によりOSがハングアップする状況が発生
> しているのですが、コマンドを実行しなくても同様の状況が発生し得るのでしょうか?

発生し得ます。が、高見さんの使い方では発生しないと思います。

Groongaはテーブル・カラムを使うときに初めて「開き」ます。逆
に言うと一度も使わないテーブル・カラムは開きません。

高見さんの使い方は、たくさんのPGroongaのインデックスがあるが、
通常使うのはその一部、だと思っています。その場合は一部の
(Groongaの)テーブル・カラムしか開かないのでメモリー使用量
が抑えられます。

すべてのテーブルに対して「SELECT ... WHERE column @@ "XXX"」
を実行するとio_flushを使用した時と同程度のメモリー使用量にな
ると思います。

>> ただ、まだ開いていないテーブル・カラムはフラッシュする必要は
>> ないので、本当は開く必要はありません。近い将来、このケースの
>> ときは開かないようにする予定です。
> 
> 現時点でクラッシュ時の破損を回避しつつ、メモリ消費量を減らす事は可能でしょうか?

はい、可能です。

> io_flushコマンドで--target_nameを指定してインデックスを1つずつ処理することでメモリ
> 使用量を抑えられるのは確認したのですが、これでクラッシュ時の問題を解決できるのかが
> 不明です。

変更がある(Groongaの)テーブル・カラムを網羅できていれば大
丈夫です。

DDLを教えてもらえればどんなio_flushを発行すれば網羅できてい
るかを伝えることができます。

「SELECT pgroonga.flush("INDEX_NAME")」とすれば大丈夫になるよ
うな関数を提供するのがいい気がしてきました。

> つまり、テーブル毎に実行するにしても、作成もしくはtruncate直後のみにした方が良いと
> いうことですね。

いえ、それだと(SQLの)INSERT/UPDATEで追加・更新されたデータ
が失われる可能性があるので、インデックスの破損を防ぐ目的なら、
直後だけでなくデータ更新後のタイミングでも実行する必要があり
ます。

>> > テーブルに対して一切の操作を行っていない、つまり、上記Selectコマンドを連
>> > 続実行した場合でも、毎回同程度の容量が確保されています。
>> 
>> これは、実行する毎にメモリー使用量が増えていくということです
>> か?たとえば、↑の「データサイズ250MBのテーブルが1つ」のとき
>>>> 
>>   * 1回実行したら初期状態から135MB増え、
>>   * 2回実行したら初期状態から270MB増え、
>>   * 3回実行したら初期状態から405MB増え、
>>   * ...
>> 
>> ということですか?であればメモリーリークな気がするので調べて
>> 直した方がよさそうに思っています。
> 
> いいえ。1回目を実行して5秒後に2回目を実行してもメモリー使用量が変わらなかったとい
> うことです。

よかったです。

   * 1回実行したら初期状態から135MB増えた状態になり、
   * 2回実行したら初期状態から135MB増えた状態になり、
   * 3回実行したら初期状態から135MB増えた状態になり、
   * ...

ということですね。

> ドキュメントの
>  メモリー上に多くの変更があるなら、それらをディスクに書き出す処理は重い処理になります。
> の記述から、このコマンドを実行してからDBに一切変更が加えられていない場合、次回実行
> 時には殆どリソースを消費しない(処理が軽い)と考えていました。

なるほど。
「処理が重い」がどういうことかの認識が違うということがわかり
ました。

私は「処理が重い」は「実行に時間がかかる」という意味で使って
いて、「メモリー使用量については何も触れていない」というつも
りでした。

> 上記の例で言うと、1回目が135MBなら、DBに変更を加えていない状態で実行された2回目は
> ほぼ0MBとなるはず、といった感じです。

つまり、こういうことですよね。

   * 1回実行したら初期状態から135MB増えた状態になりまた初期状態と同じ状態に戻り、
   * 2回実行したら初期状態から135MB増えた状態になりまた初期状態と同じ状態に戻り、
   * 3回実行したら初期状態から135MB増えた状態になりまた初期状態と同じ状態に戻り、
   * ...

実際は、1回目で確保したメモリーは以後も使い回すため、メモリー
使用量は「初期状態から135MB増えた状態」から変わりません。
「135MB増えた状態から初期状態に戻り」ません。


-- 
須藤 功平 <kou****@clear*****>
株式会社クリアコード <http://www.clear-code.com/>
10周年祝いイベント: https://clear-code.doorkeeper.jp/events/48646

Groongaベースの全文検索システムを総合サポート:
  http://groonga.org/ja/support/
パッチ採用 - プログラミングが楽しい人向けの採用プロセス:
  http://www.clear-code.com/recruitment/




groonga-dev メーリングリストの案内
Back to archive index