[pgsql-jp: 33494] Re: select文でセグメンテーション違反

Hitoshi Taniguchi taniguchi @ chihaya-t3.co.jp
2004年 7月 5日 (月) 13:57:35 JST


谷口@質問者です。

> SELECT count(*) FROM test50m ORDER BY key1;
は、以下のメッセージがでて実行できませんでした。
Attribute test50m.key1 must be GROUPed or used in an aggregate function
もちろん、石井殿の意図は分かりましたので以下をテストしてOKでした。
SELECT count(*) FROM test50m;
さらに、以下もOKでした。
SELECT key1 FROM test50m;
SELECT key1 FROM test50m ORDER BY key1;
つまり、SORT等の処理が終了した後、結果を全てpsqlに取り込み
その時点で、メモリのオーバーフローになるということだと理解できます。
そこまでは、私も理解できるのですが、実際にはそう単純でも無いようです。
SELECT * FROM test50m; でエラーになるのが理解できません。
仮想記憶は、16GByeで、理由は、以下の通りです。
=================================================
free -m
                total          used     free   shared   buffers    cached
Mem:         7810          265      7545         0          13          93
-/+ buffers/cache:       159      7651
Swap:       16001             0     16001
以上の状態で以下を実行し、free -m -s 1で状態をモニタしてみました。
SELECT * FROM test50m;
エラー終了した時点では、以下の状態です。psqlも終了しています。
free -m
                total          used     free   shared   buffers    cached
Mem:         7810        4123      3687         0          19        3835
-/+ buffers/cache:       267      7543
Swap:       16001             0     16001
しかし、psで確認するとpsql実行分のpostmasterは、未だ稼動しており、
一定時間後、psで終了したことを確認して、再度メモリを確認すると
free -m
                total          used     free   shared   buffers    cached
Mem:         7810        7786         24         0          25        7391
-/+ buffers/cache:       368      7441
Swap:       16001             0     16001
となっています。この状態で、再度同じ処理を実行してみました。
SELECT * FROM test50m;
同様にfree -m -s 1で状態をモニタしてみました。
free -m -s 1 は、使用量が増え続け、エラーが出始めて頃がピークで
                total          used     free   shared   buffers    cached
Mem:         7810          7793         17         0          1        4518
-/+ buffers/cache:       3272      4538
Swap:       16001         1161     14840
となります。エラー終了からメモリ使用量は減り続けますが、
その後、実メモリだけ使用量が増え、postmasterが終了した時点では、
free -m
                total          used     free   shared   buffers    cached
Mem:         7810        7241        569         0           6        6910
-/+ buffers/cache:       324      7485
Swap:       16001             2     15998
と、なります。
=================================================
何かがパンクをしているということは分かるのですが、
その何かが分かりません。
念のためにテストした問題無さそうな共有メモリの設定と横に
その初期設定値(Linuxとpostgresql.conf)を以下に記載(#以下)します。
少なくともこの2種類の設定ではエラーが出ます。
「hugememカーネル」は、未確認事項があるため、現時点では使用していません。
<sysctl.conf側>
kernel.shmall = 2097152            #2097152(これだけ初期値どおり)
kernel.shmmax =  278888448     #33554432
<postgresql.conf側>
 max_connections = 8                #32
 shared_buffers = 32768             #64
 max_fsm_relations = 200            #1000
 max_fsm_pages = 1048576          #10000
 max_locks_per_transaction = 16   #64
 sort_mem = 262144                  #1024
 vacuum_mem = 262144             #8192
 effective_chashe_size = 32768    #1000
以上です。
kernel.shmmaxの値は、小さすぎるとps_ctl start時点で、指示される
sizeの値をそのまま使用しています。
kernel.shmallは、kernel.shmmaxと同一値でもテストしましたが、
「ipcs -l」でmax total shared memoryが桁あふれすることがあるので
初期値に戻してテストをしています。
何か初歩的な誤解をしているところがあるのでしょうか?
何かアドバイスを頂けますと助かります。

> 石井です.
>
> > 谷口@質問者です。
> >
> > > > パラメータを論理的に調整してみる事からはじめませんか?
> > > 一つずつ挑戦してみます。
> > 色々と試してたところ、処理速度に変化は見られるものの
> > ----------------------------------------------------------
> > SELECT * FROM table_name ORDER BY key1,key2,key3,key4;
> > server sent data ("D" message) without prior row description ("T"
message)
> > server sent data ("D" message) without prior row description ("T"
message)
> > ・・・延々と続きます
> > セグメンテーション違反です
> >
> >      以上の様にして終了します。SELECTの実行から約30分後です。
> > ----------------------------------------------------------
> > の状況は、変化がありませんでした。
> > カーネルとPostgreSQLの両方の設定を全て初期状態に
> > 戻してみましたが結果は同じでした。
> >
> > ===============================
> > <再度整理してみました>
> > 大規模データ(100-200GB程度)のデータ分析に以下のサーバを
> > スタンドアロンで使用するという単純な使用方法です。
> > CPU: Xeon MP * 2CPU
> > メモリ: 8GB
> > OS: Red Hat Enterprise Linux ES Version 3
> > PostgreSQL:Version 7.3.6
> > ディスク:ext3(但し、raid5)で、700GB程度のユーザエリアで処理
> >
> > ===============================
> > 問題を簡単にする為に以下のテストを行いました。
> > DROP TABLE test1m;
> > CREATE TABLE test1m(
> >     key1    char(5),
> >     key2    char(5),
> >     key3    char(5),
> >     key4    char(5),
> >     pad     char(80)
> > );
> > ランダムな数字を作成して、test1mに百万件登録し、
> > 同様にテーブル名をtest50mにして5千万件登録しました。
> > 実際のテーブルサイズは別とすると、
> > test1mには、約100MByteのデータ容量になり
> > test50mには、約5GByteのデータ容量になります。
> >
> > psqlにより、以下の実験をしました。
> > <test1mに対して>
> > 1)SELECT * FROM test1m ORDER BY key1;
> > 2)SELECT * FROM test1m ORDER BY key1 LIMIT 5;
> > 3)SELECT * FROM test1m ORDER BY key1 OFFSET 999995;
> > 4)SELECT * FROM test1m;
> > 5)SELECT * FROM test1m LIMIT 5;
> > 6)SELECT * FROM test1m OFFSET 999995;
> > <test50mに対して>
> > 7)SELECT * FROM test50m ORDER BY key1; <= ERROR *****
> > 8)SELECT * FROM test50m ORDER BY key1 LIMIT 5;
> > 9)SELECT * FROM test50m ORDER BY key1 OFFSET 999995;
> > 10)SELECT * FROM test50m; <= ERROR *****
> > 11)SELECT * FROM test50m LIMIT 5;
> > 12)SELECT * FROM test50m OFFSET 49999995;
> > 前述のエラーが出たのは、7)と10)でした。
>
> psqlも同じホストで動かしているのですか?だったら7)とか10)がNGなのは当
> 然です.5GBのテーブルを全部psqlのメモリにコピーしようとしているんです
> から.
>
> たとえば,
>
> SELECT count(*) FROM test50m ORDER BY key1;
>
> とすればたぶんエラーにならないと思います.
>
> あと,swapはどの位設定しているんですか?8GBのメモリを搭載しているのな
> ら,その2倍の16GB以上は用意しないと,Linuxの場合仮想メモリを使い果たし
> たときの動作が怪しくなると思います.
>
> というわけで,アドバイスとしては,
>
> o 処理中で使用しているメモリをきちんと計算
> o 仮想メモリがその分用意されているかどうか考える
>
> ということでしょうか.
> --
> Tatsuo Ishii





pgsql-jp メーリングリストの案内