我正在尝试使用另一个表 (B) 中包含的地址数据对一个表 (A) 中的数据进行地理编码。由于街道名称的写法可能不同,我想先浏览 A 中的数据,然后在给定的邮政编码区域内,为每个元组找到 B 中最接近 A 元组中的街道名称的街道名称。对于文本匹配,我目前正在使用 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)
乙
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
有关如何提高此功能的效率的任何提示?