十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

PostgreSQL大表查询慢?pg_pathman分区工具完整解读:让亿级数据查询快10倍的秘密

PostgreSQL大表查询慢?pg_pathman分区工具完整解读:让亿级数据查询快10倍的秘密 PostgreSQL大表查询慢pg_pathman分区工具完整解读让亿级数据查询快10倍的秘密【免费下载链接】pg_pathmanPartitioning tool for PostgreSQL项目地址: https://gitcode.com/gh_mirrors/pg/pg_pathmanpg_pathman是一款为 PostgreSQL 打造的高性能分区工具Partitioning tool for PostgreSQL它通过优化的分区机制和自定义执行计划节点让分区表查询避免全盘扫描从而显著提升亿级大表的查询与写入性能。如果你正被 PostgreSQL 大表查询慢、插入慢、维护难的问题困扰这篇文章将带你完整读懂 pg_pathman 的加速原理与使用方法。为什么 PostgreSQL 大表查询会这么慢当一张表的数据量增长到千万、亿级时即使加了索引也会遇到这些问题规划器开销大传统基于表继承的分区方案规划器必须逐个检查每个分区的 CHECK 约束分区越多规划时间越长删除成本高清理历史数据只能DELETE产生大量死元组写入无路由插入数据要靠触发器手动分拣性能损耗明显。PostgreSQL 10 引入了原生声明式分区但 pg_pathman 在它之前就已提供了一套更彻底的优化方案尤其适合 PostgreSQL 9.5~10 时代的表继承分区也能兼容原生分区。 核心矛盾数据必须拆成小表才快但拆表后查询又要聪明地只访问相关小表。pg_pathman 解决的就是聪明地找表这件事。快速开始4 步安装 pg_pathman 分区工具安装非常直接只需 4 步第 1 步编译安装make install USE_PGXS1第 2 步配置共享预加载库修改postgresql.conf项目中的 conf.add 就是这个配置示例shared_preload_libraries pg_pathman第 3 步重启 PostgreSQL 实例必须重启插件依赖共享内存第 4 步创建扩展CREATE SCHEMA pathman; GRANT USAGE ON SCHEMA pathman TO PUBLIC; CREATE EXTENSION pg_pathman WITH SCHEMA pathman;⚠️ 注意如果同时使用pg_stat_statements等使用相同钩子的扩展建议按shared_preload_libraries pg_stat_statements, pg_pathman的顺序排列避免冲突。pg_pathman 加速原理3 个核心机制 pg_pathman 为什么快拆开来看有 3 个关键设计。1. 配置表 共享内存缓存pg_pathman 把分区方案记录在pathman_config配置表中每行记录一张分区表的表名、分区列、分区类型并在初始化阶段将各分区边界信息缓存到共享内存。规划阶段查哪个分区不再靠逐个试探约束而是直接查缓存结构。配置存储定义见 README.md 中的 Views and tables 章节分区信息解析逻辑位于 src/relation_info.c2. 二分查找代替穷举扫描查询条件如WHERE id 150或WHERE dt 2015-06-01中pg_pathman 会识别分区键 比较运算符 常量的结构然后RANGE 分区对分区边界做二分查找毫秒级定位目标分区HASH 分区用统一哈希函数直接算出唯一分区。规划器据此只把相关分区放进执行计划——365 个日分区里查 2 天数据实际只扫描 2 个分区。-- 只查 6 月 1~2 日的数据执行计划只涉及 2 个分区 EXPLAIN SELECT * FROM journal WHERE dt 2015-06-01 AND dt 2015-06-03; -- 结果Append - Seq Scan on journal_152 / journal_1533. 5 个自定义执行计划节点pg_pathman 基于 PostgreSQL 的 CustomScan API 实现了 5 个自定义计划节点这是它区别于普通触发器方案的关键节点名称作用源码位置RuntimeAppend运行时按参数值挑选分区应对id (SELECT ...)这类计划期未知的条件src/runtime_append.cRuntimeMergeAppend有序查询时的运行时分区挑选src/runtime_merge_append.cPartitionFilterINSERT 时的智能分拣器直接把行重定向到目标分区取代传统触发器src/partition_filter.cPartitionRouter跨分区 UPDATE 时定位目标分区src/partition_router.cPartitionOverseer协调跨分区 UPDATE本质是 DELETE INSERTsrc/partition_overseer.c举个例子id ANY (SELECT ...)这种子查询条件参数值在计划阶段无法确定。没有RuntimeAppend时只能扫描全部 100 个分区有了它执行期才动态挑选 4 个真正相关的分区README 中的实测数据显示执行时间从2.059 ms 降到 0.101 ms接近 20 倍差距。RANGE 与 HASH 两种分区模式上手示例RANGE 分区适合日志、订单等时间序列数据-- 创建日志表并建立索引父表索引会自动复制到每个分区 CREATE TABLE journal (id SERIAL, dt TIMESTAMP NOT NULL, level INTEGER, msg TEXT); CREATE INDEX ON journal(dt); -- 按天分区自动创建 365 个分区并迁移数据 SELECT create_range_partitions(journal, dt, 2015-01-01::date, 1 day::interval);后续数据超出范围时新分区会自动创建RANGE 分区独有特性也可手动管理SELECT add_range_partition(journal, 2016-01-01::date, 2016-01-07::date); -- 指定范围 SELECT append_range_partition(journal); -- 追加一个默认区间的新分区HASH 分区适合高并发写入的通用表-- 按 id 哈希成 100 个分区 SELECT create_hash_partitions(items, id, 100);查询时 pg_pathman 自动排除父表只扫描命中分区EXPLAIN SELECT * FROM items WHERE id 1234; -- 结果Append - Index Scan using items_34_pkey on items_34只扫 1 个分区 两种模式都支持表达式分区和复合键支持整数、浮点、日期等类型含 domain 类型。函数完整签名见 README.md 的 Available functions 章节。6 个实用管理技巧运维效率翻倍无阻塞数据迁移存量表分区时用partition_table_concurrently()启动后台工作进程按小批量短事务搬运数据每批最多 1 万行不影响线上业务分区拆分与合并热点分区用split_range_partition()一拆为二冷数据用merge_range_partitions()合并不用重建表整分区秒级删除drop_range_partition(journal_1, true)直接删掉最老的分区比DELETE快几个数量级冷数据下沉到远端通过attach_range_partition()把历史数据外置表甚至postgres_fdw远程表挂成分区查询时透明访问写入也能经PartitionFilter重定向过去分区创建回调用set_init_callback()注册回调函数新分区创建时自动执行如自动建索引、设置表空间视图随时体检pathman_partition_list查看所有分区及边界pathman_concurrent_part_tasks查看迁移进度pathman_cache_stats查看缓存内存占用。-- 一键查看某个表的所有分区和范围 SELECT * FROM pathman_partition_list WHERE parent journal::regclass;GUC 调优开关精细控制分区行为pg_pathman 提供了一组pg_pathman.*参数可按需开关各功能参数用途pg_pathman.enable整体启用/禁用 pg_pathmanpg_pathman.enable_runtimeappend开关 RuntimeAppend 节点pg_pathman.enable_partitionfilter开关 INSERT 分区路由pg_pathman.enable_partitionrouter开关跨分区 UPDATEpg_pathman.enable_auto_partition会话级开关自动建分区pg_pathman.insert_into_fdw控制是否允许写入外部表分区pg_pathman.override_copy开关 COPY 语句的分区加速单表永久退出管理可用disable_pathman_for(表名)数据原样保留回退到标准继承机制。源码结构速览想深入阅读从哪里入手整个项目核心代码集中在src/目录约 2.3 万行 C 代码建议按以下路径阅读入口与初始化src/init.c钩子注册、共享内存、src/pg_pathman.c扩展主入口分区创建src/partition_creation.c2000 行涵盖 RANGE/HASH 全部分区操作INSERT 路由src/partition_filter.c1600 行PartitionFilter 节点实现执行优化src/runtime_append.c、src/partition_overseer.c版本兼容src/compat/pg_compat.c适配 PostgreSQL 11~15 的差异测试用例sql/ 目录下 30 个功能测试脚本tests/ 包含 CMocka 单元测试与 Python 集成测试使用建议pg_pathman 与原生分区怎么选根据 README.md 的官方说明pg_pathman 目前处于维护期仅修复支持版本的 Bug不再新增功能支持 PostgreSQL 11~15。官方建议新建 PostgreSQL 10 项目优先考虑成熟的原生声明式分区PARTITION BY RANGE/HASH存量 PG 9.5 继承式分区、或需要无阻塞迁移/远程分区下沉/复杂分区运维pg_pathman 依然是工具箱里的利器。总结pg_pathman 通过配置表 共享内存缓存 二分查找 自定义计划节点的组合拳把分区表的找表成本从线性降到了对数级再用PartitionFilter免触发器路由写入、用后台工作进程实现无阻塞迁移——这正是它让亿级数据查询提速一个数量级的完整秘密。对于正在被 PostgreSQL 大表拖慢业务的同学不妨先在你的日志表或订单表上试验 RANGE 分区配合EXPLAIN观察执行计划的变化体感会非常直接。【免费下载链接】pg_pathmanPartitioning tool for PostgreSQL项目地址: https://gitcode.com/gh_mirrors/pg/pg_pathman创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表