邮政编码和城市名称的匹配-在PostgreSQL中非常慢

邮政编码和城市名称的匹配-在PostgreSQL中非常慢,postgresql,sql-update,sql-like,Postgresql,Sql Update,Sql Like,我正在尝试使用othertable中的数据更新mytable中的地址字段。 若我匹配邮政编码并从mytable中的othertable中搜索城市名称,它的运行速度相当快。但由于我并不是在所有情况下都有邮政编码,所以我也只想在第二个查询中查找姓名。这需要超过12小时的时间。我能做些什么来加快查询速度?请注意,索引没有帮助。索引扫描在2没有更快 用于匹配邮政编码+名称1的代码 update mytable t1 set admin1 = t.admin1, admin2 = t.admin2, ad

我正在尝试使用othertable中的数据更新mytable中的地址字段。 若我匹配邮政编码并从mytable中的othertable中搜索城市名称,它的运行速度相当快。但由于我并不是在所有情况下都有邮政编码,所以我也只想在第二个查询中查找姓名。这需要超过12小时的时间。我能做些什么来加快查询速度?请注意,索引没有帮助。索引扫描在2没有更快

用于匹配邮政编码+名称1的代码

update mytable t1 set
admin1 = t.admin1,
admin2 = t.admin2,
admin3 = t.admin3,
postal_code = t.postal_code,
lat = t.lat,
lng = t.lng from (
select * from othertable) t
where t.postal_code = t1.postal_code and     t1.country = t.country
and upper(t1.address) like '%' || t.admin1 || '%' --looks whether city name from othertable shows up in address in t1
and admin1 is null;
仅在名称2上匹配的代码

update mytable t1 set
admin1 = t.admin1,
admin2 = t.admin2,
admin3 = t.admin3,
postal_code = t.postal_code,
lat = t.lat,
lng = t.lng from (
select * from othertable) t
where t1.country = t.country
and upper(t1.address) like '%' || t.admin1 || '%' --looks whether city name from othertable shows up in address in t1
and admin1 is null;
查询计划1:

"Update on mytable t1           (cost=19084169.53..19205622.16 rows=13781     width=1918)"
"  ->  Merge Join  (cost=19084169.53..19205622.16 rows=13781 width=1918)"
"        Merge Cond: (((t1.postal_code)::text = (othertable.postal_code)::text) AND (t1.country = othertable.country))"
"        Join Filter: (upper((t1.address)::text) ~~ (('%'::text || othertable.admin1) || '%'::text))"
"        ->  Sort  (cost=18332017.34..18347693.77 rows=6270570 width=1661)"
"              Sort Key: t1.postal_code, t1.country"
"              ->  Seq Scan on mytable t1  (cost=0.00..4057214.31 rows=6270570 width=1661)"
"                    Filter: (admin1 IS NULL)"
"        ->  Materialize  (cost=752152.19..766803.71 rows=2930305 width=92)"
"              ->  Sort  (cost=752152.19..759477.95 rows=2930305 width=92)"
"                    Sort Key: othertable.postal_code, othertable.country"
"                    ->  Seq Scan on othertable  (cost=0.00..136924.05 rows=2930305 width=92)"
查询计划2:

"Update on mytable t1     (cost=19084169.53..27246633167.33 rows=5464884210 width=1918)"
"  ->  Merge Join  (cost=19084169.53..27246633167.33 rows=5464884210 width=1918)"
"        Merge Cond: (t1.country = othertable.country)"
"        Join Filter: (upper((t1.address)::text) ~~ (('%'::text || othertable.admin1) || '%'::text))"
"        ->  Sort  (cost=18332017.34..18347693.77 rows=6270570 width=1661)"
"              Sort Key: t1.country"
"              ->  Seq Scan on mytable t1  (cost=0.00..4057214.31 rows=6270570 width=1661)"
"                    Filter: (admin1 IS NULL)"
"        ->  Materialize  (cost=752152.19..766803.71 rows=2930305 width=92)"
"              ->  Sort  (cost=752152.19..759477.95 rows=2930305 width=92)"
"                    Sort Key: othertable.country"
"                    ->  Seq Scan on othertable (cost=0.00..136924.05 rows=2930305 width=92)"

在第二个查询中,您或多或少地加入了city name,但是othertable在每个city name中有多个条目,因此您在每个记录中更新mytable几次,具有不可预测的值,lat long或其他admin2/3将是最后一个更新的

如果othertable包含没有邮政编码的条目,请通过添加额外条件使用它们,并且othertable.posalcode为空

否则,您将希望获得othertable的子集,该子集为每个admin1+国家/地区值返回一行。您将用以下查询替换othertable中的select*。当然,您可能需要调整它,以获得比第一个更高的lat/long/admin2-3

选择admin1、country、firstpostal\u code postal\u code、firstlat lat、firstlng lng、firstadmin2 admin2、firstadmin3 admin3 从其他表格 按admin1分组,国家/地区 最糟糕的是,第二个查询覆盖了第一个查询中更新的内容,因此您必须通过添加和mytable.postalcode为空来忽略这些记录

整个查询可能是

更新mytable t1 设置 admin1=t.admin1, admin2=t.admin2, admin3=t.admin3, 邮政编码=t.邮政编码, lat=t.lat, 液化天然气=吨液化天然气 从…起 选择admin1、country、firstpostal\u code postal\u code、firstlat lat、firstlng lng、firstadmin2 admin2、firstadmin3 admin3 从其他表格 按管理员1分组,t国 其中t1.country=t.country 和uppert1.address类似“%”| | t.admin1 | |“%”-查看othertable中的城市名称是否显示在t1中的地址中 admin1为空 并且mytable.postal_代码为空;
您是否希望在第二个查询中更新大约54亿行?好的,我想我现在明白问题所在了。但是,我需要计算lat/lng的平均值,而不仅仅是使用每个国家/地区的第一个值