他の2つのテーブルからテーブルを作成しようとしています。私のコードは動作しますが、実際には遅いです(gnameレコードにつき20msなので、完了には3 +日かかるでしょう)。postgresqlの最適化(高速化)11MioレコードのLOOPが25k行と一致するようにする
基本的に私は11mioポイントと25kグリッドを持っており、グリッドをそれぞれのポイントにリンクするテーブルを生成したいと考えています。私は、次の後に1つのgnameレコードを実行し、その半径内のいずれかのグリッドの中心点がST_DWithinであるかどうかを確認します。もし私がその情報を保存したいならば。
- gnamesテーブルは11Mioレコードを有し、各レコードは、複数のグリッド(MAX4)であることができる
- グリッドテーブルは、私は数を設定する(サイクルを用いて、以下の機能を書いた25Kレコード
を有しますループ)とlpoffset(特定のポイントから開始します)、DBは、それだけで一日、何のために実行させることがDBに書き込まれたときにクラッシュしたので(ループが完了一度だけ、それが書かれているようだ?)
CREATE OR REPLACE FUNCTION gnames_to_grid(cycles integer, lpoffset integer)
RETURNS integer AS
$BODY$
DECLARE
r RECORD;
index integer:=lpoffset;
BEGIN
RAISE NOTICE 'start';
FOR r IN
SELECT gnameid, the_gm FROM gname LIMIT cycles OFFSET lpoffset
LOOP
EXECUTE 'INSERT INTO gname_grid
SELECT ' || r.gnameid || ', grid.id FROM grid
WHERE ST_DWithin(' || quote_literal(r.the_gm::character varying) || ',the_gm,100000,true) ';
index = index +1;
--count number of records written to table
RAISE NOTICE 'after: %', quote_literal(index);
END LOOP;
-- return next offset
RAISE NOTICE 'end';
RETURN index;
END
$BODY$
LANGUAGE plpgsql VOLATILE
私は15%のCPUと30%のRAMを使います。私はDBの値をより多く使うように設定しましたが、使用や速度の変更はありません。 lpoffsetのために、私は同時に2回機能を実行させてからCPUを30%にすることができますが、もっと良い解決策があるはずです。誰かが私にこれを改善する方法を教えることができたら、とても嬉しく思っています。
おかげ
EDIT: "wildpassers"
からの質問に答えるために、あなたは地理フィールドにインデックスを持っていますか?
GNは(座標列上の)インデックスが
grが、彼らは箱を(座標列上の)インデックス
(https://github.com/colemanm/gazetteer/blob/master/docs/geonames_postgis_import.mdから学んだ)
をバウンディングしているかしていましたか?
I私は関数を使用して自動的にやったのに - 下のリンクの下に最初のノートを参照してください
ST_DWithin function
有効な統計情報がありますか?
ここではどういう意味ですか?
クエリプランは何ですか? LOOPのため
- それは関数と呼ばれているとして、それはすべての詳細を表示していないようだ(それはまた、1000行で実行された)、または単に
"Result (cost=0.00..0.26 rows=1 width=0) (actual time=26714.823..26714.823 rows=1 loops=1)"
"Planning time: 0.017 ms"
"Execution time: 26714.836 ms"
を「説明」よりも、他のいくつかの方法があります登録しよう
"Insert on geoname_grid_2 (cost=0.00..1597498489.76 rows=1000 width=8) (actual time=28343.040..28343.040 rows=0 loops=1)"
" -> Limit (cost=0.00..1597498479.76 rows=1000 width=8) (actual time=52.782..28319.443 rows=1000 loops=1)"
" -> Nested Loop (cost=0.00..150564231717.67 rows=94250 width=8) (actual time=52.781..28319.214 rows=1000 loops=1)"
" Join Filter: (((gn.the_geom)::geography && st_expand((gr.the_geom)::geography, '100000'::double precision)) AND ((gr.the_geom)::geography && st_expand((gn.the_geom)::geography, '100000'::double precision)) AND _st_dwithin((gn.the_geom)::geo (...)"
" Rows Removed by Join Filter: 15969526"
" -> Seq Scan on geoname gn (cost=0.00..590016.50 rows=11064750 width=36) (actual time=0.004..0.545 rows=625 loops=1)"
" -> Materialize (cost=0.00..816.31 rows=25554 width=36) (actual time=0.000..1.150 rows=25553 loops=625)"
" -> Seq Scan on grid gr (cost=0.00..688.54 rows=25554 width=36) (actual time=0.233..5.001 rows=25554 loops=1)"
"Planning time: 0.202 ms"
"Trigger for constraint geoname_grid_2_geoname_geonameid_fkey: time=129.146 calls=1000"
"Trigger for constraint geoname_grid_2_grid_id_fkey: time=78.144 calls=1000"
"Execution time: 28551.360 ms"
サーバー・チューニングのための
?
サーバはIntelCore I7、12ギガバイトRAM、Winows 10 OSのチューニングのための
(私はここでの主なポイントを全体のファイルを添付するための方法を見つけることができませんでした)何か他のものが有用であろうなら、私が知っている-LEtです:
max_connections = 20
shared_buffers = 512MB
effective_cache_size = 9GB
work_mem = 100488kB
maintenance_work_mem = 1536MB
min_wal_size = 4GB
max_wal_size = 8GB
checkpoint_completion_target = 0.9
wal_buffers = 16MB
default_statistics_target = 500
おかげ
ループやダイナミックSQLは必要ありません(テーブル名やカラム名のどれも可変ではありません)プレーンSQLに書き直すことができます。 (ただし、LIMITとOFFSETが干渉する可能性があります) – wildplasser
私はwildplasserに同意します:ループや動的SQL(または関数)を必要としません –