查询以获取 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.04

Postgres 设置

我在 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 中的条件的主要内容,如果未能解决你的问题,请参考以下文章

如何获取不同 SQL 表中每一行的 PKey 和价格?

比较 php MySQL 查询结果数组以从其中一个数组中获取关联值

Python sqlalchemy查询标签或别名结果两列作为新列名

SQL NOT BETWEEN 查询

如何列出各个列,其中每个列包含一个 id 计数,其中每列中的 id 不在 MySQL 中每列的不同表中

如何获取多项选择的结果并合并为一行