1

別のテーブル (B) に含まれる住所データを使用して、あるテーブル (A) のデータをジオコーディングしようとしています。通りの名前は異なる書き方をする可能性があるため、最初に A のデータを調べて、各タプルについて、特定の郵便番号ゾーン内で A のタプルの名前に最も近い通りの名前を B で見つけたいと思います。テキスト マッチングには、現在、pg_trgm 拡張機能の similarity() 関数と '%' 演算子を使用しています。

A にはさまざまな国のデータが含まれているため、関数パラメーターにはそれぞれのテーブル名が含まれていますが、扱っている国と住所データ テーブル (B) の関連フィールドの名前も含まれています。

それぞれのテーブルの関連フィールドは次のとおりです。

id            | bigint                | non NULL
cp            | character varying     |
rue           | character varying     | 
rue_trouvee   | character varying     | 
iso_pays      | character varying     | 

インデックス付き:

"tableA_temp_pkey" PRIMARY KEY, btree (id)
"idx_tableA_pays" btree (iso_pays)

B

rue              | character varying(90) | 
code_post        | character varying(5)  | 
x                | double precision      | 
y                | double precision      | 

インデックス付き:

"idx_fradresses_code_post" btree (code_post)
"idx_fradresses_rue_trgm" gin (rue gin_trgm_ops)

現在、私はこの PLPGSQL 関数を使用しています:

CREATE OR REPLACE FUNCTION trouver_rue_proche(datatable TEXT, addresstable TEXT, address_rue TEXT, address_cp TEXT, pays TEXT) RETURNS INTEGER AS $$
DECLARE

rec_data RECORD;
nom_rue RECORD;

counter INTEGER;

BEGIN

    counter := 0; 

    FOR rec_data IN
       EXECUTE SELECT id, rue, cp FROM ' || quote_ident(datatable) || ' WHERE iso_pays = ' || quote_literal(pays) || ' AND x is null'
   LOOP

       counter := counter + 1;
       EXECUTE 'SELECT ' || quote_ident(address_rue) || ' as rue_t FROM geocode.' ||   quote_ident(addresstable) || ' WHERE ' || quote_ident(address_cp) || ' = ' || quote_literal(rec_data.cp) || ' AND ' || quote_ident(address_rue) || ' % ' || quote_literal(rec_data.rue) || ' ORDER BY similarity(' || quote_ident(address_rue) || ', ' || quote_literal(rec_data.rue) || ') DESC LIMIT 1' INTO nom_rue;
       EXECUTE 'UPDATE ' || quote_ident(datatable) || ' SET rue_trouvee = $1 WHERE id = $2' USING nom_rue.rue_t, rec_data.id;
    END LOOP;

    RETURN counter;

END

$$

LANGUAGE plpgsql;

584,670 個のタプルがまだ x=NULL であり、住所テーブルに 25,228,340 個のタプルが含まれている国に対してこの関数を実行しようとすると、この関数はほぼ 3 日間実行されています。

私のマシンの仕様は次のとおりです。

Intel(R) Core(TM) i3-3225 CPU @ 3.30GHz
8GB RAM

postgresql.conf で次のパラメータを使用して PostgreSQL 9.1 を実行しています。

shared_buffers = 4096MB
work_mem = 512MB

この関数の効率を改善する方法に関するヒントはありますか?

4

1 に答える 1