当前位置: 首页 > ops >正文

geomtry空间索引sql查询慢优化

原来sql,两个表想要通过空间索引查询交集,但是glTable的SRID是4490;cesTable 是4325
查询失败,将两个表的SRID统一成4490,而且两张表没有加空间索引
使用函数查询交集查询速度特别慢;

//慢sql 执行时间长达100s
SELECT 
a.geom, b.geometry FROM glTable as a JOIN cesTable as b ON a.geom && b.geometry AND ST_Intersects(a.geom, b.geometry);

使用执行计划查看是否走索引,发现走了索引,但是查询速度还是特别慢

EXPLAIN ANALYZE
SELECT a.geom,  b.geometry  
FROM glTable a
JOIN cesTable b 
ON a.geom && b.geometry AND ST_Intersects(a.geom, b.geometry);

继续优化

//最终版查询速度优化到0.1s
SELECT a.xse,b.*
FROM glTable a
JOIN LATERAL (SELECT * FROM cesTable b WHERE a.geom && b.geometry AND ST_Intersects(a.geom, b.geometry)
) b ON TRUE;

原因总结:

语法没有问题,但之所以执行 非常慢,
根本原因在于以下几点(尤其是你提到“两个差不对”——说明数据之间几乎不相交)根本原因分析数据量乘积过大 + 实际匹配度极低
如果:glTable 有 1,000 个 PolygoncesTable 有 100,000 个 Point➡️ 你这句 SQL 逻辑上相当于:对每个 polygon 去遍历所有摄像头,看是否相交(即点落在面内)理论计算量:1,000 × 100,000 = 1亿次 ST_Intersects() 判断。但现实是你说的:“感觉两个差不对”,也就是说——大多数面和点根本没有交集,相当于 99.999% 的计算都白费。PostGIS 的空间 JOIN 即使加了索引,依旧是近似 O(N×M)
虽然你用了:a.geom && b.geometry AND ST_Intersects(a.geom, b.geometry)
其中 && 是用了 GiST 空间索引的快速预筛选(bounding box),但只要两个表都很大,性能依旧撑不住。

建议改为“以面为主、点为辅”的逐面计算方式
推荐写法(逐面 LATERAL 方式):

SELECT a.id_1,b.cam,b.geometry
FROM glTable a
JOIN LATERAL (SELECT cam, geometry FROM cesTable b WHERE a.geom && b.geometry AND ST_Intersects(a.geom, b.geometry)
) b ON TRUE;

✅ 以每个 polygon 为主,查其范围内可能的点

✅ 利用空间索引缩小搜索空间

✅ 极大减少无效 ST_Intersects 的计算次数

✅ 加强优化建议:
➤ 1. 看看是否真的有交集(先打印有几条)

SELECT COUNT(*) FROM glTable ;
SELECT COUNT(*) FROM cesTable ;SELECT COUNT(*) 
FROM glTable a
JOIN cesTable b ON a.geom && b.geometry AND ST_Intersects(a.geom, b.geometry);

👉 如果第三条结果非常少(<1000),那就绝对不应该全表 JOIN。

➤ 2. 打印所有相交 ID 看看“哪里交集了”

SELECT a.id_1, b.cameraindexcode
FROM glTable a
JOIN LATERAL (SELECT cam, geometry FROM cesTable b WHERE a.geom && b.geometry AND ST_Intersects(a.geom, b.geometry)
) b ON TRUE;

➤ 3. 如仍需全量匹配,可用以下方式并行优化:

– 允许并行处理

SET max_parallel_workers_per_gather = 4;
SET parallel_tuple_cost = 0.1;
SET parallel_setup_cost = 0.1;

✅ 总结

问题说明
❌ 全量 JOIN 空间判断会导致数亿次空间比较,极慢
✅ 大部分面和点不重叠造成计算几乎都浪费
✅ 索引虽然生效,但无法避免计算量过大&& 只能帮你部分过滤
✅ 推荐使用 LATERAL 查询减少无效计算,优化数十倍
http://www.xdnf.cn/news/16206.html

相关文章:

  • Android 的16 KB内存页设备需要硬件支持吗,还是只需要手机升级到Android15系统就可以
  • [python][基础]Flask 技术栈
  • 软件工程之可行性研究:从理论到实践的全面解析
  • JAVA知识点(四):SpringBoot与分布式、微服务架构
  • 腾讯云CodeBuddy+微信小程序:5分钟开发番茄小闹钟
  • ClickHouse 高性能实时分析数据库-物化视图篇
  • 【lucene】如何给StandardAnalyzer添加charfilter
  • P1106 删数问题 - 洛谷
  • Multiscale Structure Guided Diffusion for Image Deblurring 论文阅读
  • 用友ERP 反射xss漏洞复现(CVE-2025-2709)
  • [NLP]多电源域设计的仿真验证方法
  • Linux运维新人自用笔记(Rsync远程传输备份,服务端、邮箱和客户端配置、脚本)
  • 编译器-gcc/g++和自动化构建-make/Makefile
  • AI冲击搜索?谷歌说:恰恰相反
  • C语言第 9 天学习笔记:数组(二维数组与字符数组)
  • 优秀案例:基于python django的智能家居销售数据采集和分析系统设计与实现,使用混合推荐算法和LSTM算法情感分析
  • Java 大视界 -- 基于 Java 的大数据分布式存储在工业互联网数据管理与边缘计算协同中的创新实践(364)
  • 矩阵谱分解的证明及计算示例
  • JVM相关面试八股
  • 虚拟机docker elasticsearch启动失败
  • Elasticsearch-ik分析器
  • 三维图像识别中OpenCV、PCL和Open3D结合的主要技术概念、部分示例
  • Java设计模式-代理模式
  • 《Angular+Spring Boot:ERP前端采购销售库存协同架构解析》
  • FalconFS: Distributed File System for Large-Scale Deep Learning Pipeline——论文阅读
  • ReVQ (Quantize-then-Rectify,量化后修正)
  • [MMU] Table walk flow详解
  • IAR编辑器如何让左侧的工具栏显示出来?
  • MCP工具开发实战:打造智能体的“超能力“
  • GaussDB 逻辑备份实操