PostGISで非常に大きなデータセットを返すクエリ


8

数百万行を返すPostGISクエリがあります。

SELECT 
 t1.id AS id1,
 t2.id AS id2,
 ABS(t1.mean_h - t2.mean_h) AS h_diff, 
 ST_Distance(t1.the_geom, t2.the_geom) AS dist  
FROM tas_ponds as t1, tas_ponds as t2 
WHERE
 (t1.gid > t2.gid) AND
 ST_DWithin(t1.the_geom, t2.the_geom, 17000)

で実行するとpsqlout of memory for query resultエラーが発生します。

Googlingは、これはpostgres / PostGISではなくpsql内のエラーであることを示唆しています。クエリをフォームにSELECT ... INTO x FROM ...修正すると問題が解決しますか?非常に大きなデータセットを処理するために推奨される他の方法はありますか?

回答:


7

これをPostgresクライアントの問題であると確認する人もいます。空間やサーバーの考慮事項とは関係ありません。クライアントには、結果を画面に表示する前にバッファするメモリ量に制限があります。

これを処理するための推奨アプローチは、DECLARE / FETCHアプローチを使用して、結果セット全体よりも小さいブロックのデータにアクセスすることです。クエリのコンポーネント(距離など)を含むビューを作成して、クエリ操作自体に必要なメモリを削減することもできます。


5

scwは2分遅れてくれたので、彼の答えは繰り返さない。その他の可能な解決策は次のとおりです。

  • Memoryセクションを編集しpostgresql.confます。クエリの実行を妨げる可能性がある非常に低いメモリ設定があるかどうかを確認してください。

  • 次のコマンドを使用して、クエリをファイルに書き込み、コマンドラインから実行してみます。

    psql -fファイル名db_name> output_file

  • 外部アプリケーションで結果を使用する場合は、外部からカーソルを使用してクエリを実行してみてくださいpsql。たとえば、クエリを実行するPythonスクリプト:

脚本:

try:
    conn = psycopg2.connect("dbname='' user='' host='' password=''") # Fill in
    cur = conn.cursor()
except:
        print 'Unable to connect to the database'
else:
        print 'Connected to database.'

query="""YOUR
         QUERY
         HERE"""
cur.execute(query)

カーソルは反復可能であるため、次のいずれかを行うことができます。

for result in cur:
    print result

またはそれらすべてを入手してください:

 results=cur.fetchall()

2
私は間違っている可能性がありますが、最初の(そしておそらく2番目の)ソリューションが機能するとは思いません。最初の1つはサーバーのメモリを変更します。これはクライアントの問題であり、DMBS内の使用可能なメモリとは関係ありません。2つ目は、画面にバッファリングすることが問題でない限り、同じ問題が発生する可能性があります。3番目のソリューションは、IMOよりも優れています。カーソルを使用して柔軟な環境で細かく制御できるため、生のSQLでは少しトリッキーです。+1
scw 2010

@scwあなたはおそらく最初の(そしておそらく2番目の)ソリューションについて正しいでしょう。問題は、これらの特定のトリックがPostgreSQLで機能するように見える場合があり、一般的なパフォーマンスが向上する可能性があり、試行するための時間と労力がほとんどないことです。あなたの答えから多くを学びました。
Adam Matan

2

記録のために、私の場合、返されたデータセットを、機能するSELECT ... INTO ...構文を使用して別のテーブルに格納しました。

これはメモリ不足の問題を解決しただけでなく、元のクエリよりも大幅に高速でした。


1

PostgresとPostGISではインデックス作成が非常に重要です

http://postgis.refractions.net/docs/ch04.html#id2794434

非常に大きなデータセットにはGiST(一般化検索ツリー)インデックスを推奨します...(これも「nullセーフ」です)例CREATE INDEX [indexname] ON [tablename] USING GIST([geometryfield]);

インデックスを構築した後、PostgreSQLにクエリ統計の最適化に使用されるテーブル統計を強制的に収集させることが重要です

VACUUM ANALYZE [table_name] [column_name]; SELECT UPDATE_GEOMETRY_STATS([table_name]、[column_name]);

また、適切なリファレンスは次のとおりです。インデックスの 活用http://postgis.refractions.net/docs/ch04.html#id2794685


はい、テーブルにインデックスを付けてバキュームを実行し、インデックスがEXPLAINなどを介して使用されていることを確認しました。ただし、問題は速度ではなく(現時点では)、メモリ不足エラーです。
fmark
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.