在Postgresql中对空间数据进行表分区的实践

在数据库管理中,合理地对数据进行分区可以提高查询性能和数据管理效率。
在这里插入图片描述

本文将详细介绍在Postgresql中对空间数据进行表分区的实践过程。

测试计算机容量有限,测试最大数据量为1,000,000条。

关键字: Postgresql PostGIS 表分区 空间数据

测试计算机配置如下:

内存(16G)
内存 1 名称为 3200 MHz,大小 8GB,频率 3200 MHz,数据宽度 64。
内存 2 名称为 3200 MHz,大小 8GB,频率 3200 MHz,数据宽度 64。
CPU(AMD 6 核 4600Hz)
- CPU 名称为超微半导体 AMD Ryzen 5 4600H with Radeon Graphics
- 六核,核心数 6,默认频率 3000 MHz,外频 100 MHz,当前频率 3000 MHz,
- 二级缓存为 512-KB,12-way set associative,64-byte line size,
- 三级缓存为 64-KB,18-way set associative,64-byte line size,
- CPU 电压 1.200 V,数据宽度 64。
硬盘(SSD): Micron MTFDHBA512TDV,大小 512GB。

一、Postgresql分区介绍

Postgresql的分区功能允许将一个大表按照特定的规则拆分成多个小的分区表。这样做的好处在于,在查询数据时,可以只扫描相关的分区,而不必扫描整个大表,从而大大提高查询速度。对于大规模数据的管理,分区还可以使得数据的维护和操作更加便捷,例如备份、恢复等操作可以针对单个分区进行,减少了资源消耗和时间成本。

二、对空间字段进行分区的基本思路

在对空间数据进行分区时,我们需要根据空间数据的特点来确定分区策略。这里我们采用了基于经纬度的分区方式。具体来说,通过计算每个数据点的经纬度与特定步长(这里是5度)的比值,然后取整,得到对应的分区索引。再根据分区索引构建分区表的名称,从而将数据划分到不同的分区中。这样的分区策略可以使得在查询时,能够快速定位到可能包含目标数据的分区,减少不必要的数据扫描。

三、基本步骤

(一)创建表和插入数据

  1. 首先创建了名为public.t_partition的表,该表包含id(大整数类型)和geom(几何类型)两个字段:
DROP TABLE IF EXISTS public.t_partition;
CREATE TABLE IF NOT EXISTS public.t_partition
(id bigint NOT NULL,geom geometry NOT NULL
);
  1. 然后向表中插入了1000000条模拟数据。数据的生成通过generate_series函数生成自增的id,并使用随机函数生成经纬度坐标,再将其转换为几何点类型并设置SRID为4326:
delete from public.t_partition;
INSERT INTO public.t_partition (id, geom)
SELECTs.id,ST_SetSRID(ST_MakePoint(random() * 360 - 180, random() * 180 - 90), 4326)
FROMgenerate_series(1, 1000000) AS s(id);
  1. 插入数据后,通过以下语句查看了插入情况的前10条数据:
select * from t_partition limit 10;

(二)创建分区函数

创建了一个名为partition_function的函数,用于根据经纬度计算分区名称。该函数接受经纬度作为参数,首先计算经度和纬度分别除以5的整数值,然后根据这些值构建分区名称。分区名称的格式为p_<经度分区值>_<纬度分区值>,其中经度和纬度分区值在构建时将负号替换为下划线:

CREATE OR REPLACE FUNCTION partition_function(longitude double precision, latitude double precision)
RETURNS text AS $$
DECLARElong_part int;lat_part int;partition_name text;
BEGINlong_part := floor((longitude)/5);lat_part := floor((latitude)/5);partition_name := format('p_%s_%s', replace((long_part*5)::varchar,'-','_'), replace((lat_part*5)::varchar,'-','_'));RETURN partition_name;
END;
$$ LANGUAGE plpgsql IMMUTABLE;

可以通过以下语句测试分区函数:

SELECT partition_function(-122,-32);

(三)创建分区表模板

创建了一个名为public.t_partition_template的表作为分区表模板,它的结构与public.t_partition相同,并通过PARTITION BY LIST根据分区函数partition_function(ST_X(geom), ST_Y(geom))对数据进行分区:

CREATE TABLE IF NOT EXISTS public.t_partition_template
(LIKE public.t_partition INCLUDING ALL
) PARTITION BY LIST (partition_function(ST_X(geom), ST_Y(geom)));

(四)创建实际分区

使用DO语句和循环创建了多个实际的分区表。循环遍历经度和纬度的范围,根据计算得到的分区名称创建对应的分区表。如果分区表已存在则不创建,以避免重复操作:

DO $$
DECLARElong_idx int;lat_idx int;long_val varchar;lat_val varchar;
BEGINFOR long_idx IN 0..72 LOOPlong_val := (long_idx*5-180)::varchar;long_val := replace(long_val,'-','_');FOR lat_idx IN 0..36 LOOPlat_val := (lat_idx*5-90)::varchar;		lat_val := replace(lat_val,'-','_');EXECUTE format('CREATE TABLE IF NOT EXISTS public.p_%s_%s PARTITION OF public.t_partition_template FOR VALUES IN (''p_%s_%s'')', long_val, lat_val, long_val, lat_val);END LOOP;END LOOP;
END $$;

在这里插入图片描述

(五)将数据插入分区表

将之前插入到public.t_partition表中的数据插入到分区表public.t_partition_template中:

INSERT INTO public.t_partition_template
SELECT * FROM public.t_partition;

这样表中的数据总量一样了。

(六)创建查询分区的函数

创建了一个名为query_partitions的函数,用于通过分区进行查询。该函数接受经纬度的最小值和最大值作为参数,首先计算可能包含目标数据的分区索引范围,然后构建分区名称数组。接着在循环中,对每个分区名称进行查询,如果分区表不存在则忽略异常并继续下一个分区的查询。最后将查询结果返回:

CREATE OR REPLACE FUNCTION query_partitions(long_min double precision, long_max double precision, lat_min double precision, lat_max double precision)
RETURNS TABLE (id bigint, geom geometry) AS $$
DECLARElong_part int;lat_part int;partition_name text;partition_names text[];
BEGIN-- 计算可能存在的分区索引范围FOR long_part IN greatest(floor((long_min)/5)*5, -180).. least(floor((long_max)/5)*5, 180) LOOPFOR lat_part IN greatest(floor((lat_min)/5)*5, -90).. least(floor((lat_max)/5)*5, 90) LOOPpartition_name := format('p_%s_%s', long_part, lat_part);partition_names = array_append(partition_names, partition_name);END LOOP;END LOOP;-- 在找到的分区中进行查询FOR i IN 1..array_length(partition_names, 1) LOOPBEGINRETURN QUERY EXECUTE format('SELECT id, geom FROM public.%I WHERE ST_X(geom) > %L AND ST_X(geom) < %L AND ST_Y(geom) > %L AND ST_Y(geom) < %L',partition_names[i], long_min, long_max, lat_min, lat_max);EXCEPTION WHEN undefined_table THEN-- 如果分区表不存在,忽略并继续下一个分区的查询CONTINUE;END;END LOOP;
END;
$$ LANGUAGE plpgsql;

四、测试结论

-- 在t_partition表中查询坐x大于120.5,小于150.666,y大于25.2,小于26.5
-- 耗时:180-220 ms
SELECT count(0)
FROM public.t_partition
WHERE ST_X(geom) > 120.5 AND ST_X(geom) < 150.666 AND ST_Y(geom) > 25.2 AND ST_Y(geom) < 26.5;-- 在t_partition_template表中查询坐x大于120.5,小于150.666,y大于25.2,小于26.5
-- 耗时:耗时:700 - 850 ms
SELECT count(0)
FROM public.t_partition_template
WHERE ST_X(geom) > 120.5 AND ST_X(geom) < 150.666 AND ST_Y(geom) > 25.2 AND ST_Y(geom) < 26.5;-- 通过函数在t_partition_template表中查询坐x大于120.5,小于150.666,y大于25.2,小于26.5 
-- 耗时:45 - 65 ms
SELECT count(0) FROM query_partitions(120.5,150.666,25.2,26.5);

通过对不同查询方式的耗时测试,我们可以得出以下结论:

  1. 对未分区的public.t_partition表进行查询,查询条件为ST_X(geom) > 120.5 AND ST_X(geom) < 150.666 AND ST_Y(geom) > 25.2 AND ST_Y(geom) < 26.5,耗时180-220 ms

  2. 对分区表模板public.t_partition_template进行相同条件的查询,耗时700-850 ms,相比未分区增大了。

  3. 通过创建的query_partitions函数在分区表中进行查询,耗时仅为45-65ms,性能提升显著。这表明我们的分区策略以及查询函数的设计是有效的,能够大大提高对空间数据的查询效率。通过合理的分区和查询设计,可以为数据库应用提供更高效的数据访问和处理能力。

请注意,上述并未对任何表做索引。

在这里插入图片描述

希望本文的实践过程和结论能为大家在Postgresql中处理空间数据分区提供有益的参考和借鉴。在实际应用中,可以根据数据的特点和查询需求,进一步优化分区策略和查询函数,以获得更好的性能表现。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Easy Excel合并单元格情况简单导入导出

需求 实现报表数据的导入导出&#xff0c;表格中部分数据是系统生成&#xff0c;部分数据是甲方填写&#xff0c;录入系统。 批号唯一 Maven <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.…

【modbus协议】libmodbus库移植基于linux平台

文章目录 下载库函数源码编译路径添加libmodbus 源码分析核心数据结构常用接口函数 开发 TCP Server 端开发TCP Client 端 下载库函数源码 编译路径添加 libmodbus 源码分析 核心数据结构 modbus_t结构体&#xff1a; 这是 libmodbus 的核心数据结构&#xff0c;代表一个 Mod…

机房巡检机器人有哪些功能和作用

随着数据量的爆炸式增长和业务的不断拓展&#xff0c;数据中心面临诸多挑战。一方面&#xff0c;设备数量庞大且复杂&#xff0c;数据中心内服务器、存储设备、网络设备等遍布&#xff0c;这些设备需时刻保持良好运行状态&#xff0c;因为任何一个环节出现问题都可能带来严重后…

从0到1学习node.js(express模块)

文章目录 Express框架1、初体验express2、什么是路由3、路由的使用3、获取请求参数4、电商项目商品详情场景配置路由占位符规则5、小练习&#xff0c;根据id参数返回对应歌手信息6、express和原生http模块设置响应体的一些方法7、其他响应设置8、express中间件8.1、什么是中间件…

如何搭建直播美颜SDK平台的最佳实践?美颜API的实现与集成详解

本篇文章&#xff0c;将从技术实现、平台搭建、API集成以及性能优化四个方面&#xff0c;为开发者详解如何搭建一个直播美颜SDK平台。 一、直播美颜SDK平台的技术架构 一般的美颜效果包括磨皮、亮肤、瘦脸、大眼等&#xff0c;这些效果的实现需要依赖图像增强和滤镜算法。核心…

【51单片机】第一个小程序 —— 点亮LED灯

学习使用的开发板&#xff1a;STC89C52RC/LE52RC 编程软件&#xff1a;Keil5 烧录软件&#xff1a;stc-isp 开发板实图&#xff1a; 文章目录 单片机介绍LED灯介绍练习创建第一个项目点亮LED灯LED周期闪烁 单片机介绍 单片机&#xff0c;英文Micro Controller Unit&#xff0…

创建ODBC数据源SQLConfigDataSource函数的用法

网络上没有这个函数能实际落地的用法说明&#xff0c;我实践后整理一下&#xff1a; 1.头文件与额外依赖库&#xff1a; #include <odbcinst.h> #pragma comment(lib, "legacy_stdio_definitions.lib") 2.调用函数&#xff1a; if (!SQLConfigDataSourceW(…

阿里云镜像源无法访问?使用 DaoCloud 镜像源加速 Docker 下载(Linux 和 Windows 配置指南)

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f343; vue-uniapp-template &#x1f33a; 仓库主页&#xff1a; GitCode&#x1f4ab; Gitee &#x1f…

java :String 类

在我们之前的讲解中我们已经了解了很多的Java知识&#xff0c;这节我们讲Java中字符如何定义以及关于String如何使用还有常见的string函数。 【本节目标】 1. 认识 String 类 2. 了解 String 类的基本用法 3. 熟练掌握 String 类的常见操作 4. 认识字符串常量池 5. 认识 …

江协科技STM32学习- P21 ADC模数转换器

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

基于SpringCloud的WMS管理系统源码

商品管理&#xff1a;商品类型&#xff0c;规格&#xff0c;详情等设置。 采购管理&#xff1a;采购单录入。 销售管理&#xff1a;销售单录入。 库存管理&#xff1a;库存查询、库存日志 采用前后端分离的模式&#xff0c;微服务版本前端 后端采用Spring Boot、Spring Cl…

python实现放烟花效果庆祝元旦

马上就要2025年元旦啦&#xff0c;提前祝大家新年快乐 完整代码下载地址&#xff1a;https://download.csdn.net/download/ture_mydream/89926458

vLLM推理部署Qwen2.5

vLLM vLLM 是一个用于大模型推理的高效框架。它旨在提供高性能、低延迟的推理服务&#xff0c;并支持多种硬件加速器&#xff0c;如 GPU 和 CPU。 vLLM 适用于大批量Prompt输入&#xff0c;并对推理速度要求高的场景&#xff0c;吞吐量比HuggingFace Transformers高10多倍。 …

手指关节分割系统:视觉算法突破

手指关节分割系统源码&#xff06;数据集分享 [yolov8-seg-C2f-RFAConv&#xff06;yolov8-seg-fasternet-bifpn等50全套改进创新点发刊_一键训练教程_Web前端展示] 1.研究背景与意义 项目参考ILSVRC ImageNet Large Scale Visual Recognition Challenge 项目来源AAAI Glob…

灵动AI:艺术与科技的融合

灵动AI视频官网地址&#xff1a;https://aigc.genceai.com/ 灵动AI 科技与艺术的完美融合之作。它代表着当下最前沿的影像技术&#xff0c;为我们带来前所未有的视觉盛宴。 AI 视频以强大的人工智能算法为基石&#xff0c;能够自动分析和理解各种场景与主题。无论是壮丽的自然…

网络学习/复习2套接字

LinuxCode/code26 zc/C语言程序学习 - 码云 - 开源中国

c语言中整数在内存中的存储

整数的二进制表示有三种&#xff1a;原码&#xff0c;反码&#xff0c;补码 有符号的整数&#xff0c;三种表示方法均有符号位和数值位两部分&#xff0c;符号位都是用‘0’表示“正&#xff0c;用1表示‘负’ 最高位的以为被当作符号位&#xff0c;剩余的都是数值位。 整数…

python 制作 发货单 (生成 html, pdf)

起因&#xff0c; 目的: 某个小店&#xff0c;想做个发货单。 过程: 先写一个 html 模板。准备数据&#xff0c; 一般是从数据库读取&#xff0c;也可以是 json 格式&#xff0c;或是 python 字典。总之&#xff0c;是数据内容。使用 jinja2 来渲染模板。最终的结果可以是 h…

使用 telnet 连接 dubbo 服务调用暴露的 dubbo 接口

目录 前言 环境准备 Telnet客户端 zookeeper pom 配置文件 dubbo接口 telnet连接dubbo dubbo命令 ls invoke 前言 工作中的微服务项目远程调用使用的技术是 dubbo&#xff0c;当对外提供了一个 duboo 接口时&#xff0c;无论是开发阶段自测&#xff0c;还是上线了服…

【EndNote版】如何在Word中引用文献

1、在Word中&#xff0c;鼠标光标放在所需插入文献的位置 2、点击选项卡中的“EndNote X9”&#xff0c;直接在EndNote中选中对应的文献 3、选中文献&#xff0c;点击工具栏中的“引用” 4、最后就可在Word中看到所插入的文献