基于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性能优化实战之-周边搜索查询

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

论文阅读笔记——PathAFL:Path-Coverage Assisted Fuzzing

文章目录 前言PathAFL&#xff1a;Path-Coverage Assisted Fuzzing1、解决的问题和目标2、技术路线2.1、如何识别 h − p a t h h-path h−path&#xff1f;2.2、如何减少 h − p a t h h-path h−path的数量&#xff1f;2.3、哪些h-path将被添加到种子队列&#xff1f;2.4、种…

深度学习环境配置常见指令

首先打开anaconda prompt&#xff0c;激活对应虚拟环境。 导入torch并获取对应版本 import torch torch.__version__导入torchvision并获取对应版本 import torchvision torchvision.__version__ 检查cuda是否可用 torch.cuda.is_available() 获取CUDA设备数 torch.cuda.…

VS中使用xcopy生成后命令报9009错误

错误现象: download下来的代码&#xff0c;在另一台电脑能使用生成后命令xcopy&#xff0c;换一台电脑后该命令不能使用&#xff0c;报如下错误&#xff1a; 2.错误原因&#xff1a; 这是因为xcopy /Y 为Windows程序命令&#xff0c;xcopy其实是Windows下的一个xcopy.exe,如果…

前后端分离Vue+ElementUI+nodejs蛋糕甜品商城购物网站95m4l

本文主要介绍了一种基于windows平台实现的蛋糕购物商城网站。该系统为用户找到蛋糕购物商城网站提供了更安全、更高效、更便捷的途径。本系统有二个角色&#xff1a;管理员和用户&#xff0c;要求具备以下功能&#xff1a; &#xff08;1&#xff09;用户可以修改个人信息&…

NXP实战笔记(十):S32K3xx基于RTD-SDK在S32DS上配置CAN通信

目录 1、概述 2、SDK配置 2.1、配置目标 2.2、CAN配置 3、代码实现 4、测试结果 1、概述 S32K3xx的FlexCan与之前的S32K1xx很相似,Can的中断掩码寄存器(IMASK3)与中断标志位寄存器(IFLAG3)依赖于邮箱数。 FlexCan配置实例如下 FlexCan的整体图示如下 Protocol Engine…

LeetCode二叉树中的第 K 大层和

题目描述 给你一棵二叉树的根节点 root 和一个正整数 k 。 树中的 层和 是指 同一层 上节点值的总和。 返回树中第 k 大的层和&#xff08;不一定不同&#xff09;。如果树少于 k 层&#xff0c;则返回 -1 。 注意&#xff0c;如果两个节点与根节点的距离相同&#xff0c;则…

Node.js+vue校内二手物品交易系统tdv06-vscode前后端分离

二手物品交易系统采用B/S架构&#xff0c;数据库是MySQL。网站的搭建与开发采用了先进的nodejs进行编写&#xff0c;使用了vue框架。该系统从三个对象&#xff1a;由管理员和用户、店铺来对系统进行设计构建。主要功能包括&#xff1a;个人信息修改&#xff0c;对用户、店铺、二…

uniapp 使用 z-paging组件

使用 z-paging 导入插件 获取插件进行导入 自定义上拉加载样式和下拉加载样式 页面结构 例子 搭建页面 <template><view class"content"><z-paging ref"paging" v-model"dataList" query"queryList"><templ…

【Java】输入输出流(实验八)

目录 一、实验目的 二、实验内容 三、实验小结 一、实验目的 1、掌握java I/O的基本原理。 2、掌握标准输入输出流和Scanner类的基本使用方法。 3、掌握FileInputStream、FileOutStream、FileReader、FileWriter、BufferedReader 、BufferedWriter类的常用方法。 二、实验…

从源码学习单例模式

单例模式 单例模式是一种设计模式&#xff0c;常用于确保一个类只有一个实例&#xff0c;并提供一个全局访问点。这意味着无论在程序的哪个地方&#xff0c;只能创建一个该类的实例&#xff0c;而不会出现多个相同实例的情况。 在单例模式中&#xff0c;常用的实现方式包括懒汉…

创建一个基于Node.js的实时聊天应用

在当今数字化社会&#xff0c;实时通讯已成为人们生活中不可或缺的一部分。无论是在社交媒体平台上与朋友交流&#xff0c;还是在工作场合中与同事协作&#xff0c;实时聊天应用都扮演着重要角色。与此同时&#xff0c;Node.js作为一种流行的后端技术&#xff0c;为开发者提供了…

Linux修改shell工具连接端口

nano /etc/ssh/sshd_config 或者 vi /etc/ssh/sshd_config 或者 vim /etc/ssh/sshd_config

2024最新版(黑客技术)零基础入门自学网络安全

一、自学网络安全学习的误区和陷阱 1.不要试图先以编程为基础的学习再开始学习 我在之前的回答中&#xff0c;我都一再强调不要以编程为基础再开始学习网络安全&#xff0c;一般来说&#xff0c;学习编程不但学习周期长&#xff0c;而且实际向安全过渡后可用到的关键知识并不…

如何连接ACL认证的Redis

点击上方蓝字关注我 应用程序连接开启了ACL认证的Redis时与原先的方式有差别&#xff0c;本文介绍几种连接开启ACL认证的Redis的Redis的方法。 对于RedisACL认证相关内容&#xff0c;可以参考历史文章&#xff1a; Redis权限管理体系(一&#xff09;&#xff1a;客户端名及用户…

AIGC 实战:Ollama 和 Hugging Face 是什么关系?

Ollama和 Hugging Face 之间存在着双重关系&#xff1a; 1. Ollama是 Hugging Face 开发并托管的工具&#xff1a; Ollama是一个由 Hugging Face 自行开发的开源项目。它主要用于在本地运行大型语言模型 (LLM)&#xff0c;特别是存储在 GPT 生成的统一格式 (GPT-Generated Un…

【Java程序设计】【C00296】基于Springboot的4S车辆管理系统(有论文)

基于Springboot的4S车辆管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的4S店车辆管理系统 本系统分为销售员功能模块、管理员功能模块以及维修员功能模块。 管理员功能模块&#xff1a;管理员登录进入4S…

招聘APP开发实践:技术选型、架构设计与开发流程

时下&#xff0c;招聘APP成为了企业和求职者之间连接的重要纽带。本文将深入探讨招聘APP的开发实践&#xff0c;重点关注技术选型、架构设计以及开发流程等关键方面&#xff0c;带领读者走进这一充满挑战与机遇的领域。 一、技术选型 在开始招聘APP的开发之前&#xff0c;首…

MacOs 围炉夜话

文章目录 一、安装 Mac 一、安装 Mac macOS是一套由苹果开发的运行于Macintosh系列电脑上的操作系统。macOS是首个在商用领域成功的图形用户界面操作系统。 VM虚拟机怎么安装mac os&#xff1f;&#xff08;全教程&#xff09; 虚拟机&#xff1a;VMware Workstation 17 pro W…

解锁创意灵感,探索FlutterExampleApps项目的奥秘

解锁创意灵感&#xff0c;探索FlutterExampleApps项目的奥秘 项目简介 FlutterExampleApps项目是一个包含各种示例应用链接的仓库&#xff0c;旨在演示Flutter应用开发中的各种功能、特性和集成。 项目包含了以下几个部分&#xff0c;每个部分都涵盖了不同的内容和主题&…

HTML5和CSS3提高

一、HTML5的新特性 增加了一些新的标签&#xff0c;新的表单&#xff0c;新的表单属性&#xff0c;IE9以上版本的浏览器才支持 注意&#xff1a; 这些语义化标准主要针对搜索引擎的 新标签可以使用多次 在IE9中需要把这些元素转化为块级元素 新增的多媒体标签 主要包含两个…