基于PostGIS的慢查询引起的空间索引提升实践

目录

前言

一、问题定位

1、前端接口定位

2、后台应用定位

3、找到问题所在

二、空间索引优化

1、数据库查询

2、创建空间索引

3、geography索引

4、再看前端响应

总结


前言

        这是一个真实的案例,也是一个新入门的工程师很容易忽略的点。往往在设计数据库的时候忘了进行索引的构建,进而由此导致了查询的性能很拉胯。下面来简单还原一下事件的经过。在之前的博客中,原文博客地址如下:基于SpringBoot和PostGIS的震中影响范围可视化实践、解决Thymeleaf的地震震中距离展示[[]]双引号报错的问题,这两篇博客中都详细介绍了如何进行空间查询的实战。

        在这些应用的建设过程当中,在进行震中范围定位时,我们发现了一个问题,就是页面请求后端的时间比较长,界面要等很久才能获取结果。 下面是我们进行网络跟踪的结果。

        通过观察network网络请求可以很直观的看到,有一个接口的请求时间很慢,就是获取震中位置的接口最慢的接近4秒才返回数据。 到底是什么原因导致了请求这么慢呢?

        本文将详细分析在PostGIS中,怎么排查数据查询慢接口,如何进行空间索引的构建,以及使用空间索引的正确姿势,通过空间索引的构建提升空间查询的效率。对致力于空间查询优化的小伙伴们有一定的参考价值。闲言少叙,下面正式进入正题。

一、问题定位

        对于一个工程师而言,遇到问题是家常便饭。比如上面这个慢查询的问题,首先这个问题很容易重现,只要点击一个地震信息点,就会请求后台。我们通过去后台调试查看具体的问题。从前端作为入口,到后台方法的定义。我们来谈谈如何进行接口调试,以至于定位查询慢的问题。

1、前端接口定位

        在浏览器中打开调试窗口,在刚刚打开的调试窗口中,可以看到网络请求一栏。在这一栏中,我们可以看到访问比较慢的接口地址。

        这里可以看到很详细的请求地址,下面将参数列出来: 

序号参数名
1request urlhttp://192.168.31.64:8080/earthqadmin/eq/mapview/villageinfo
2request methodpost
3payloadlng 117.03 lat 34.32

        通过这里的请求url,我们可以找到后台对应的接口。由于这里没有采用网关模式部署,因此直接对接的是系统后台。

2、后台应用定位

        在后台代码当中,我们找到对应的controller类,并找到了对应的方法定义,接口代码如下:

/**
* 震中位置5公里分析
* @param lng 经度
* @param lat 纬度
* @return
*/
@PostMapping("/villageinfo")
@ResponseBody
public AjaxResult earthinfo(String lng,String lat){
    List<EarthquakeVillageVo> list = earthquakeInfoService.findListByLngLat(lng, lat);
    AjaxResult ar = AjaxResult.success();
    ar.put("data", list);
    return ar;
}

        代码比较简单,直接接收参数,并将参数传递到service层(这里并不会消耗时间),我们来看看Service的定义。

@Override
public List<EarthquakeVillageVo> findListByLngLat(String lng, String lat) {
	return villageMapper.findListByLngLat(" 'point(" +lng+" "+lat+")' ");
}

        通过代码发现,这里也没有进行复杂计算,继续来看Mapper的处理逻辑:

static final String FIND_LIST_BY_LNG_LAT = "<script>"
			+ "with bp as ( select st_geomfromtext(${pointinfo},4326) :: geography tp ) "
			+ "select st_distance(t.geom :: geography, bp.tp) dist,t.address,t.village_name,t.lng,t.lat from biz_village t, "
			+ " bp where st_dwithin(t.geom :: geography, bp.tp, 5000 ) order by dist "
			+ "</script>";
@Select(FIND_LIST_BY_LNG_LAT)
List<EarthquakeVillageVo> findListByLngLat(@Param("pointinfo")String pointinfo);

3、找到问题所在

        通过接口的代码分析,我们发现其逻辑非常简单,最终只是去数据库进行空间查询。那由此我们可以将问题排查的方向从应用代码转移到数据库中。应该是数据库的查询性能导致了查询性能的下降。顺着这种思路,我们来进行数据库调优,尝试优化查询性能。

二、空间索引优化

        为了验证我们的猜想,也同时为了让系统性能有一个提升,我们将执行的sql语句复制到navicate中进行性能验证。sql语句如下:

with bp as 
(
	select st_geomfromtext('point(111.99 40.34)',4326) :: geography tp
)
select st_distance(t.geom :: geography, bp.tp),t.*  from biz_village t,bp  where st_dwithin(t.geom :: geography, bp.tp, 5000);

1、数据库查询

        数据库的表biz_village表的数据量在65W左右,这个量其实不算大。毕竟空间数据,上千万条数据都是有可能的。

        首先我们在客户端工具navicate中执行上述语句,看一下实际的查询性能怎么样?来看一下实际的运行结果。执行时间1.79秒,确实有点慢。

         上述语句在数据库中执行,确实比较慢,一共耗时1.8秒,导致后台接口的性能很差。由此证明我们的优化方向是正确的,的确是数据查询性能低导致访问慢。因此问题的关键就变成了查询优化。通常在数据库中的优化步骤是什么呢?优化成本最低的是索引。我们来看一下实际语句,这里用到一个空间函数st_dwithin()。

with bp as 
(
	select st_geomfromtext('point(111.99 40.34)',4326) :: geography tp
)
select st_distance(t.geom :: geography, bp.tp),t.*  from biz_village t,bp  where st_dwithin(t.geom :: geography, bp.tp, 5000);

        首先我们来看一下数据库表索引,

         惊讶的发现,表里面没有设计空间索引,因此来看一下执行执行计划:

        很明显,这里面没有任何的索引生效,似乎查询慢也是意料之中。既然怀疑是索引问题,那么我们来创建数据库索引。

2、创建空间索引

        这里使用以下语句进行空间所用的创建,创建索引耗时将近10秒。这也是为什么索引要提前创建,不然这些索引创建的时间成本也是挺高的,随着数据量的增大是个很恐怖的数字。

create index idx_biz_village_geom on biz_village using gist(geom)
> OK
> 时间: 9.447s

        在创建了空间索引后,来看一下查询性能是否提升。

        然而并没有什么提升,难道是索引无效吗?继续打开执行计划看一下。发现其依然没有走索引。是不是很奇怪。

         肯定有细心的朋友发现了问题,我们仔细来看一下where条件。

where st_dwithin(t.geom :: geography, bp.tp, 5000);

         在st_dwithin函数中,我们把原本的geometry类型转换为了geography,之所以转换是因为我们想精确计算范围,比如5公里。众所周知,在4326坐标系下,如果使用geomerty的距离计算单位是度,而不是我们熟悉的米。我们先将转换去掉,先来验证索引是否有效。

        仔细对比一下之前的查询计划,发现这里用到了索引查询,0.1表示0.1度,并不是0.1米。请各位朋友注意。 再来执行以下sql语句,是不是很惊喜,查询时间只需要0.006秒。这说明空间索引的构建对于提升空间查询速度帮助很大。

3、geography索引

        这里需要思考一个问题,我们给geometry设计了索引,那geography为什么没有用呢?这也好理解,这两个其实都是空间数据库中空间数据的两种表达。使用geography主要为了精确的计算距离,而使用度来转换的话,不同坐标系下会有一定的误差。但是怎么进行geography的数据索引构建呢?可以使用下面语句来进行。

create index idx_biz_village_geom_gp on biz_village using gist((geom::geography))
> OK
> 时间: 10.513s

        空间索引创建完毕后,再来看执行计划:

        再次执行空间查询,效果依然很明显。优化后执行时间耗时0.009秒。

        从1.8秒到0.009秒,速度提升了 200倍。

4、再看前端响应

        经过上述的空间索引优化后,我们来看一下界面的展示情况。经过数据库优化,界面访问速度大幅提升,可以实现毫秒级响应。用户体验进一步的提升。

总结

        在应用程序的开发过程中,一定要重视索引的使用和创建,好的索引应用能提升应用的查询性能。不好的索引设计,将会使用户体验大大降低。最后提一点最佳实践建议,针对于空间索引,一定要提前建立,因为空间索引的创建耗时太长。在上述的空间索引中,既有geometry的空间索引,又有geography的索引,个人建议,如果不是为了精确计算米级查询,只需要创建geometry索引即可。这样也减少空间索引的创建成本。

        以上就是本文的主要内容,本文将详细分析在PostGIS中,怎么排查数据查询慢接口,如何进行空间索引的构建,以及使用空间索引的正确姿势,通过空间索引的构建提升空间查询的效率。对致力于空间查询优化的小伙伴们有一定的参考价值。行文仓促,定有不当之处,如有不当之处,欢迎各位专家和朋友批评指正,十分感谢。在空间索引优化过程中参考了以下博客资料,站在巨人的肩膀上,才能看得更高更远。

参考资料地址:

1、postgis性能优化实战之-周边搜索查询

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/405765.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【JVM】Java中SPI机制

打破双亲委派模型中提到SPI和JDBC相关内容&#xff0c;那么是如何打破双亲委派模型呢?本文进行一个讲解&#xff0c;在开始讲解之前&#xff0c;我们需要先了解Java中的SPI机制 是什么 SPI 全称Service Provider Interface&#xff0c;是 Java 提供的一套用来被第三方实现或…

《TCP/IP详解 卷一》第6章 DHCP

目录 6.1 引言 6.2 DHCP 6.2.1 地址池和租用 6.2.2 DHCP和BOOTP消息格式 6.2.3 DHCP和BOOTP选项 6.2.4 DHCP协议操作 6.2.5 DHCPv6 6.2.6 DCHP中继 6.2.7 DHCP认证 6.2.8 重新配置扩展 6.2.9 快速确认 6.2.10 位置信息&#xff08;LCI和LoST&#xff09; 6.2.11 移…

股票量化系统QTYX“单针探底”迎战A股V型反转|24年2月春节后第一周记录

前言 “实战案例个股画像”系列和大家分享我基于QTYX选股框架&#xff0c;在实战中选股的案例&#xff0c;和大家一起见证QTYX选股框架逐步完善的过程&#xff0c;帮助大家理解QTYX的精髓。 关于QTYX的使用攻略可以查看链接&#xff1a;QTYX使用攻略 关于QTYX初衷和精髓可以查看…

【计算机毕业设计】541鲜花商城系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

Unity 2021.3发布WebGL设置以及nginx的配置

使用unity2021.3发布webgl 使用Unity制作好项目之后建议进行代码清理&#xff0c;这样会即将不用的命名空间去除&#xff0c;不然一会在发布的时候有些命名空间webgl会报错。 平台转换 将平台设置为webgl 设置色彩空间压缩方式 Compression Format 设置为DisabledDecompre…

Java 学习和实践笔记(19):this的使用方法

this用来指向当前对象的地址。 this的用法&#xff1a; 1&#xff09;在普通方法中&#xff0c;this总是指向调用该方法的对象。在普通方法中&#xff0c;它是作为一种隐式参数一直就存在着&#xff08;这句话的意思&#xff0c;就是其实在普通方法中&#xff0c;编译器一直就…

Word第一课

文章目录 1. 文件格式1.1 如何显示文件扩展名1.2 Word文档格式的演变1.3 常见的Word文档格式 3. 文档属性理解文档属性查看文档属性 4. 显示比例方式一&#xff1a; 手动调整方式二&#xff1a; 自动调整 5. 视图、窗口视图 1. 文件格式 1.1 如何显示文件扩展名 文档格式指的…

Vue2页面转化为Vue3

vue2element-ui转化为Vue3element plus 后台管理系统&#xff1a;增删查改 vue2页面&#xff1a; <template><div class"app-container"><div><el-form:model"queryParams"ref"queryForm"size"small":inline&qu…

【人脸朝向识别与分类预测】基于LVQ神经网络

课题名称&#xff1a;基于LVQ神经网络的人脸朝向识别分类 版本日期&#xff1a;2024-02-20 运行方式&#xff1a;直接运行GRNN0503.m文件 代码获取方式&#xff1a;私信博主或 企鹅号:491052175 模型描述&#xff1a; 采集到一组人脸朝向不同角度时的图像&#xff0c;图像…

刷题日记-Day2- Leedcode-977. 有序数组的平方,209. 长度最小的子数组,59. 螺旋矩阵 II-Python实现

刷题日记Day2 977 有序数组的平方209. 长度最小的子数组59. 螺旋矩阵 II 977 有序数组的平方 链接&#xff1a;https://leetcode.cn/problems/squares-of-a-sorted-array/description/ 给你一个按 非递减顺序 排序的整数数组 nums&#xff0c;返回 每个数字的平方 组成的新数组…

【Git】:初识git

初识git 一.创建git仓库二.管理文件三.认识.git内部结构 一.创建git仓库 1.安装git 使用yum install git -y即可安装git。 2.创建仓库 首先创建一个git目录。 3.初始化仓库 这里面有很多内容&#xff0c;后面会将&#xff0c;主要是用来进行追踪的。 4.配置name和email 当然也…

【MySQL系列 04】深入浅出索引

一、索引介绍 提到数据库索引&#xff0c;相信大家都不陌生&#xff0c;在日常工作中会经常接触到。比如某一个 SQL 查询比较慢&#xff0c;分析完原因之后&#xff0c;你可能就会说“给某个字段加个索引吧”之类的解决方案。 但到底什么是索引&#xff0c;索引又是如何工作的…

【python】yolo目标检测模型转为onnx,及trt/engine模型的tensorrt轻量级模型部署

代码参考&#xff1a; Tianxiaomo/pytorch-YOLOv4: PyTorch ,ONNX and TensorRT implementation of YOLOv4 (github.com)https://github.com/Tianxiaomo/pytorch-YOLOv4这个大佬对于各种模型转化写的很全&#xff0c;然后我根据自己的需求修改了部分源码&#xff0c;稍微简化了…

Linux:ACL权限,特殊位和隐藏属性

目录 一.什么是ACL 二.操作步骤 ① 添加测试目录、用户、组&#xff0c;并将用户添加到组 ② 修改目录的所有者和所属组 ③ 设定权限 ④ 为临时用户分配权限 ⑤ 验证acl权限 ⑥ 控制组的acl权限 三. 删除ACL权限 一.什么是ACL 访问控制列表 (Access Control List):ACL 通…

项目管理:如何成功完成一个项目

项目管理是一项重要的技能&#xff0c;它可以帮助你成功地完成一个项目。以下是一些关键的步骤&#xff0c;可以帮助你实现这一目标&#xff1a; 1. 明确项目目标&#xff1a;在开始项目之前&#xff0c;你需要明确项目的目标。这将有助于你制定一个明确的计划&#xff0c;并确…

JS基本知识

JS作用域的内存模型 每个函数都有各自的作用域、作用域链、变量对象、执行环境。 一、函数初始化&#xff1a;3作用域链。 函数被调用&#xff1a;1作用域、2变量对象、4执行环境。执行结束后&#xff0c;1作用域、3作用域链、4执行环境被销毁、2变量对象&#xff08;如果函…

悄悄话花费的时间(C语言)

题目描述 给定一个二叉树&#xff0c;每个节点上站着一个人&#xff0c;节点数字表示父节点到该节点传递悄悄话需要花费的时间。 初始时&#xff0c;根节点所在位置的人有一个悄悄话想要传递给其他人&#xff0c;求二叉树所有节点上的人都接收到悄悄话花费的时间。 输入描述 …

如何在 Tomcat 中为 Web 应用程序启用和配置缓存?

在Tomcat中为Web应用程序启用和配置缓存通常涉及到对Tomcat的连接器&#xff08;Connector&#xff09;进行配置&#xff0c;以及可能的话&#xff0c;配置Web应用程序本身以支持缓存。 1. 配置Tomcat连接器以启用缓存 Tomcat的连接器可以通过其配置来启用各种…

WEB相关工具(wget、curl、ab)

目录 一、wget 1、wget基本语法 2、wget帮助的更多选项 二、curl 1、curl基本语法 2、curl命令基本用法 2.1 curl伪装 2.2 提取状态码 2.3 提取本地IP地址 2.4 提取远端服务器IP地址 2.5 提取本地端口 2.6 提取远端服务器端口 三、压力测试工具 1、常用的httpd压…

通天星CMSV6 车载视频监控平台 信息泄露漏洞复现

0x01 产品简介 通天星CMSV6车载视频监控平台是东莞市通天星软件科技有限公司研发的监控平台,通天星CMSV6产品覆盖车载录像机、单兵录像机、网络监控摄像机、行驶记录仪等产品的视频综合平台。通天星科技应用于公交车车载、校车车载、大巴车车载、物流车载、油品运输车载、警车…