查询以获取 table1 中每一行的结果,其中包含 N 个最大记录的子查询,找到满足 table2 中的条件
Posted
技术标签:
【中文标题】查询以获取 table1 中每一行的结果,其中包含 N 个最大记录的子查询,找到满足 table2 中的条件【英文标题】:query to get the results of each row in table1 with a subquery of N maximum records found to meet a condition in table2 【发布时间】:2019-12-09 07:22:42 【问题描述】:我正在尝试使用 LIDAR 卫星数据集计算我所在城市的建筑高度,但没有成功。
系统规格
CPU:Core i7 6700k 4200MHz,4 核,8 线程 内存:32GB DDR4 3200mhz SSD:1TB 三星 970 EVO 操作系统:Ubuntu 18.04Postgres 设置
我在 PostGIS 中使用最新版本的 Postgres v12.1 数据库,并在不同来源中推荐了以下调整:
shared_buffers = 256MB
maintenance_work_mem = 4GB
max_parallel_maintenance_workers = 7
max_parallel_workers = 7
max_wal_size = 60GB
min_wal_size = 90MB
random_page_cost = 1.0
数据库设置
在激光雷达表中我有超过 30 亿行,在建筑物表中超过 150000 行。 在激光雷达表中创建了 GiST 索引:CREATE INDEX lidar_idx ON lidar USING GIST (geom);
建筑表:|吉德 |几何 |
激光雷达表:| z |几何 |
高度计算
目前为了计算建筑物的高度,需要检查30亿点(行)中的每一个是否在每个建筑物的区域内,并计算在建筑物区域内找到的所有点的平均值.
我尝试过的查询需要很长时间(可能超过 5 天甚至更长),我想简化查询,以便我可以用更少的点数获得建筑物的高度,而无需与每个建筑物每次都有 30 亿条记录。
例如:
对于 id1 的建筑,我只想获取在建筑几何区域 (ST_Within(l.geom, e.geom)
) 内找到的前 100 条记录,一旦找到这 100 条记录,就传递到下一个建筑。
对于 id2 的建筑,我也想要同样的方法,只获取在建筑区域内找到的前 100 条记录。
等等..
我的主要查询是
SELECT e.gid, AVG(l.z) AS height
FROM lidar l,
buildings e
WHERE ST_Within(l.geom, e.geom)
GROUP BY e.gid) t
我尝试了另一个查询,但我无法让它工作。
SELECT e.gid, AVG(l.z), COUNT(1) FILTER (WHERE ST_Within(l.geom, e.geom)) AS gidc
FROM lidar l, buildings e
WHERE gidc < 100
GROUP BY e.gid
【问题讨论】:
【参考方案1】:我认为你根本不想这样做。您应该首先尝试make the correct query faster,而不是通过处理数据的任意(但不是随机)子集来影响正确性。
但如果你确实想要,那么你可以使用横向连接。
SELECT e.gid from
buildings e cross join lateral
(select AVG(l.z) AS height FROM lidar l WHERE ST_Within(l.geom, e.geom) LIMIT 100)
需要检查30亿个点(行)中的每一个是否在每个建筑物的区域内,并计算在一个建筑物区域内找到的所有点的平均值。
这正是几何索引的用途。您无需查看每个点即可仅获取建筑区域内的点。如果没有合适的索引,比如on lidar using gist (geom)
,那么横向连接查询也会很糟糕。
【讨论】:
您好 jjanes,非常感谢您的帮助。我正在测试它,它似乎工作!精彩 :) 我将为这两个表添加详细设置,因此我们还可以检查哪些点是绝对必要的。在这种情况下,我使用之前添加的激光雷达索引进行了所有测试,并对 postgreSql 配置进行了一些改进,但我仍然遇到很多性能问题,这就是我拼命寻求一些可能的解决方案的原因以上是关于查询以获取 table1 中每一行的结果,其中包含 N 个最大记录的子查询,找到满足 table2 中的条件的主要内容,如果未能解决你的问题,请参考以下文章
比较 php MySQL 查询结果数组以从其中一个数组中获取关联值
Python sqlalchemy查询标签或别名结果两列作为新列名