python - 使用 PostGIS 查找最近点
问题描述
在带有 PostGIS 扩展的 PostgreSQL 12 上,我有两个表定义如下:
CREATE TABLE table_a (
id_a integer,
id_b integer,
coord geometry,
);
CREATE INDEX table_a_coord_idx ON table_a USING gist (coord);
CREATE TABLE table_b (
id_b integer,
coord geometry,
);
CREATE INDEX table_b_coord_idx ON table_b USING gist (coord);
这两个表都有大约 300 万个条目。这些coord
列仅包含点几何。的值id_b
最初为空。
我的目标是找到table_a
最近点中的每个点table_b
并填写该列id_b
。我编写了一个小的 Python 脚本来通过基于索引的 KNN 搜索来实现这一点:
import psycopg2 as pg
conn = pg.connect()
cur = conn.cursor()
cnt = 0
cur.execute('SELECT id_a, coord FROM table_a WHERE id_b IS NULL')
for row in cur.fetchall():
cnt += 1
cur.execute('SELECT id_b FROM table_b ORDER BY geom <-> %s LIMIT 1;', (row[1],))
nearest_vertex = cur.fetchone()
cur.execute('UPDATE table_a SET id_b=%s WHERE id_a=%s', (nearest_vertex[0], row[0]))
if cnt % 1000 == 0:
conn.commit()
conn.commit()
此代码有效。但平均需要 0.6 秒才能完成一个条目,因此完成所有条目需要大约三周的时间。
有谁知道如何加快这个过程?
解决方案
在循环中逐个处理记录会导致大量网络流量流向数据库。
相反,尝试在单个语句中一次更新所有条目(如果您愿意,可以从 pyton 脚本发送)。
UPDATE table_a
SET id_b = (
SELECT id_b
FROM table_b
ORDER BY table_b.geom <-> table_a.geom
LIMIT 1
)
WHERE id_b IS NULL;
推荐阅读
- list - Spring Cloud Stream - 一对多转换
- ios - 使用拖放委托拖动集合视图的单元格时如何覆盖滚动行为?
- javascript - 如何使用 findOne 通过不同的对象 id (_id) 比较两个数组对象?
- python - 如何将决策变量的结果传递给 Docplex python 中的另一个模型?
- php - 有没有办法在数据库更改时通知 WordPress 管理员?
- reactjs - 如果在 React 中将我的 API 密钥存储在环境变量中是不安全的,我如何检索此密钥以便可以访问 AWS API Gateway 上的端点?
- c++ - 这三个旨在获取 int 数组长度的函数的真正区别是什么?
- c# - 使用 Automapper 对两种不同类型进行相同的映射
- scala - sc.parallelize 中的 num_slices 参数是什么意思?
- sql-server - 设置变量时的 SQL 性能