PostgreSQL 运维实战系列,第五期:容量规划与分区策略设计
Clyde Jin
04-24
DBA
57

PostgreSQL 运维实战系列,第五期:容量规划与分区策略设计

0. 前言:数据库不是无限增长的容器

前四期我们完成了生产环境搭建、高可用部署、性能调优和故障诊断。但还有两个问题经常被忽视直到最后一刻才暴露:数据库还能撑多久?数据量大了怎么办?

一个表从 1GB 增长到 1TB,查询延迟从 10ms 飙升至 10 秒,索引膨胀、VACUUM 跑不动、备份时间从小时变成天——这不是数据库的问题,这是“没有在正确的时间做正确的容量准备”的问题。

本期聚焦两个紧密关联的主题:

  1. 容量规划:回答“数据库还能用多久”“什么时候需要扩容”“预算该怎么要”
  2. 分区策略:回答“表太大了怎么拆”“数据生命周期怎么管”“维护如何自动化”

1. 容量规划:从“拍脑袋”到“预测模型”

1.1 为什么大多数 DBA 的容量规划是错的

90% 的 DBA 曾因经验不足或认知偏差踩过容量规划的“坑”——最常见的误区是“只看今天的数据量,忽略明天的增长模式”,导致扩容永远在追着故障跑。

数据库容量规划的本质是“资源天气预报”,就像天气预报需要分析气温、湿度、风向等多维数据,容量规划需要同时考虑存储、CPU、内存、I/O 的耦合关系。

数据增长不是匀速的:

  • 线性增长:用户注册量——每天多 1000 人,稳定可预测
  • 周期性增长:电商订单——工作日低、周末高、双十一脉冲
  • 季节性增长:企业财务系统——月底、季末、年底各有高峰
  • 指数增长:短视频用户行为日志——一旦业务爆发,就是噩梦

核心原则:容量规划不能靠“感觉”,必须靠“数据”。

1.2 容量规划公式:存储、CPU、内存、I/O 四维模型

存储容量:数据本体 + 索引堆栈 + WAL 日志 + 临时文件

数据的四个空间来源分别为:

  • 表数据本体:基准可直接由 pg_total_relation_size('table_name') 捕获
  • 索引开销:每个 B-tree 索引通常占主表数据量的 50%~100%。一个 500GB 的表拥有一组复合或二级索引,再加上几个大字段,总占用可能翻倍
  • WAL 日志与临时文件:归档或流复制场景中需额外预算空间,单次大查询的临时文件可能达到 GB 级
  • 死元组膨胀:不及时 VACUUM 的表,死元组占比可能超过 20%

长期预测实施建议

  • 每日采集 pg_total_relation_sizen_tup_ins - n_tup_del 写入历史表
  • 基于过去 30 天数据做线性回归预测未来 90 天的增长趋势
  • 设置阈值:预测剩余空间少于 60 天用量时触发预警通知

2. 分区策略:设计比执行更重要

2.1 什么时候该分区?——误判比拖延更可怕

分区不是银弹。不少开发者对分区抱有“巨大表一分区就变快”的幻想——但实际上,分区的首要目标是改善维护体验(加速数据清理、简化 VACUUM、控制索引大小)。查询速度在不使用分区键时不降级已是成功。

什么时候该分区

  • 表超过 3000 万行或 50GB,维护操作(VACUUM、索引重建)耗时过长
  • 需要按时间批量删除旧数据(每月/每季度删除过期数据)——分区能秒级 DETACH,而 DELETE 则需要数小时
  • 查询模式天然带时间范围(WHERE created_at BETWEEN ...)或地域分组
  • 索引本身已大到无法全部放入内存

什么时候不该分区

  • 总数据量在 100GB 以内且增长平稳——无端增加复杂度
  • 小表(<10GB)分库分表是徒劳,额外的约束检查反而可能降低查询性能
  • 应用程序无法或不方便在查询条件中带上分区键

2.2 类型对比与选型表

分区类型 语法 典型场景 优势 限制
RANGE PARTITION BY RANGE (created_at) 时间序列表、日志、事件流 最自然的滚动淘汰方式,分区裁剪效果最好 分区键必须用于 WHERE,跨分区点查性能可能比哈希分区略差
LIST PARTITION BY LIST (region) 按地区、状态、类型分组的数据 离散值管控很简单 只支持单列分区键,不适用范围分区
HASH PARTITION BY HASH (user_id) 海量用户数据平摊,负载极度均匀 消除数据热点,均匀分布 不适用范围查询;扩容时整个集群需要人工干预重分布数据,适合预规划一次性建好足够数量的分区(如 64 或 128)

2.3 声明式分区语法速查

按日/月/季度范围分区是最常用的架构,通常搭配 created_at(时间戳)索引:

-- 创建父表
CREATE TABLE events (
    id BIGSERIAL,
    user_id BIGINT NOT NULL,
    event_type TEXT NOT NULL,
    payload JSONB,
    created_at TIMESTAMPTZ NOT NULL DEFAULT now()
) PARTITION BY RANGE (created_at);

-- 按月添加分区(建议自动化脚本执行)
CREATE TABLE events_2025_01 PARTITION OF events
    FOR VALUES FROM ('2025-01-01') TO ('2025-02-01');
CREATE TABLE events_2025_02 PARTITION OF events
    FOR VALUES FROM ('2025-02-01') TO ('2025-03-01');

-- 在父表上建自动应用到所有分区的索引(PG 11+)
CREATE INDEX idx_events_created_at ON events (created_at);
CREATE INDEX idx_events_user_id ON events (user_id);

跨分区唯一约束的限制:如果分区键不是主键的一部分,就无法在分区表上建立跨所有分区的全局唯一约束(例如一个全局唯一的 email 列)。在这种情况下,通常借助全局唯一索引(如果业务允许)或在应用层手动处理唯一性。

3. 分区表索引策略:本地 vs 全局的取舍

3.1 两种索引的本质区别

一个重要概念必须贯穿整个决策:表分了区后,索引怎么建? 两种完全不同的思路是本地索引和全局索引。

  • 本地索引:在每个分区内单独建造一个索引且结构相同,增删分区时只需操作对应索引分区,无需重建全局索引。但如果查询条件里没有分区键,就要合并多个分区索引的扫描结果,效率难以接受。
  • 全局索引:建立在父表上的单一 B-tree 索引,覆盖全表所有分区,支持跨任意字段的唯一约束与非分区键点查,但当 DETACHDROP 分区后,全局索引部分条目指向已被删除的分区,需要重建或标记为不可用。

决策检查点:每月归档有固定维护窗口的,优先本地索引;OLTP 系统几乎全部走 ID 单行点查的,非 local 不可行;跨分区查询且返回量少的,全局索引带来的单次范围扫描比扫描所有本地索引更高效。

3.2 实战对比:哪种更快?

在一份压测对比中,同样 1 亿条 sensor_data 记录:

  • 局部索引WHERE sensor_id=123 时耗时 840ms,索引大小 32GB
  • 全局索引WHERE sensor_id=123 时耗时仅 62ms,索引大小 5.2GB
  • 但跨分区时间范围查询时,全局索引反而比局部索引慢(310ms vs 120ms)

结论:没有绝对的胜负,取舍全看业务场景——高频点查优先走全局索引,范围扫描则留本地索引。

3.3 索引维护清单

日常维护检查以下几点,避免索引成为运维黑洞:

-- 定位未使用的分区索引(idx_scan=0)
SELECT schemaname, tablename, indexname, idx_scan 
FROM pg_stat_user_indexes 
WHERE idx_scan = 0 
ORDER BY schemaname, tablename;

-- 重建膨胀严重的索引
REINDEX INDEX CONCURRENTLY idx_name;

4. pg_partman:分区运维的自动驾驶仪

4.1 为什么需要 pg_partman——手工创建分区的痛

最真实的痛感:数据量一上去,手工 CREATE TABLE(按月拆分)费神又容易出错,忘记创建下月分区会让当月数据直接插入父表,父表原本没有数据,一旦存入相当于所有查询绕过分区裁剪扫描父表(空),性能急速退化但逻辑上“能跑通”,这是致命的静默性能漏洞。pg_partman(PostgreSQL Partition Manager)就是为此设计的专用扩展,自动创建和维护基于时间或 ID 的多组分区表。

-- 安装 pg_partman(需要超级用户)
CREATE EXTENSION pg_partman;

-- 按时间分区:月粒度 + 提前创建 3 个月
SELECT partman.create_parent(
    p_parent_table => 'public.events',
    p_control => 'created_at',
    p_interval => '1 month',
    p_premake => 3
);

-- 配置数据生命周期:保留 12 个月,超龄分区自动剥离
UPDATE partman.part_config 
SET retention = '12 months', 
    retention_keep_table = false,
    automatic_maintenance = 'on'
WHERE parent_table = 'public.events';

4.2 利用 pg_cron 实现自动维护周期

partman_config 中开启了 automatic_maintenance,只需在 cron 中每天调用一次 run_maintenance_proc,它就能完成“创建下月分区 + 剥离过期分区”整套流程:

-- 利用 pg_cron 调度(PG 14+ native)
CREATE EXTENSION pg_cron;
SELECT cron.schedule(
    'partition-maintenance',
    '0 2 * * *',   -- 每天凌晨 2 点执行
    'SELECT partman.run_maintenance_proc()'
);

4.3 零停机归档实战

最后一步,历史分区不应只有删除,归档到更廉价的存储介质也需要自动化:

-- 方法 1:零停机 DETACH(剥离但保留数据)
ALTER TABLE events DETACH PARTITION events_2024_01 CONCURRENTLY;
-- 剥离后可单独 pg_dump 压缩存储,或移至只读 HDD 表空间。

-- 方法 2:分区表 + 外部表归档(pg_archive 或 postgres_fdw)
-- 将冷数据迁移到低成本的归档实例上挂载为外部表,历史查询仍可透明访问

5. 数据生命周期管理:冷热分离存储

5.1 表空间分层存储

“热数据”与“冷数据”的物理隔离原则是:把高频访问的活跃热分区放在高性能 SSD 上,历史冷分区迁移到 HDD 或压缩表中,分区表本身带来的 [DETACH + ATTACH] 操作对比浪费 CPU 和 IO。表空间是实现这一目标的底层抽象,它是存储在特定位置的一个命名空间(目录),让你可以将不同对象的 I/O 压力分散到不同磁盘上:

-- 创建 SSD 和 HDD 两个表空间
CREATE TABLESPACE fastspace LOCATION '/ssd1/pgdata';
CREATE TABLESPACE slowspace LOCATION '/hdd1/pgdata';

-- 创建分区时指定存储介质
CREATE TABLE events_2025_01 PARTITION OF events 
    FOR VALUES FROM ('2025-01-01') TO ('2025-02-01')
    TABLESPACE fastspace;

-- 季度迁移:将旧分区从 SSD 迁移至 HDD
ALTER TABLE events_2024_10 SET TABLESPACE slowspace;

5.2 冷数据归档的两种主流路径

  • 独立归档库 + postgres_fdw 外部表:将过期分区迁至更廉价的归档数据库,主库通过 FDW 仍可跨库查询
  • 对象存储归档:对极冷且极少再查询的旧数据,导出 Parquet 或压缩 CSV 存入 S3/MinIO

自动化归档脚本可用 pg_cron + DETACH 实现完全自动化运作。最重要的验收环节是:归档前后比对行数和关键字段摘要,防止静默丢失数据。

6. 分区查询优化:分区裁剪失效是最大的坑

6.1 分区裁剪原理——两个阶段如何工作

PostgreSQL 执行分区查询时会根据 WHERE 子句中的常量值判断哪些分区的 CHECK 约束不匹配,从而在规划期或执行期提前排除无关分区——这就是“分区裁剪”(partition pruning),也是分区表比单表性能更优的根本原因,可以大幅减少 I/O 和计算开销。

分区裁剪失效典型场景

  • 用函数包裹分区键列WHERE date(created_at) = '2026-01-01' —— 优化器无法从函数中反推出原始列范围
  • JOIN 分区表与另一个子查询WHERE created_at = (SELECT max(...) FROM ...) —— 参数直到执行时才确定
  • 隐式类型转换created_attimestamptz,却用 DATE 类型比较,绕过索引放弃裁剪

最佳做法是显式写出完整范围或先计算后再查询,用法接近提前声明分区键的值。

6.2 检查分区裁剪是否生效

-- 在 EXPLAIN 输出中重点看这一行:
EXPLAIN (ANALYZE, BUFFERS) 
SELECT * FROM events 
WHERE created_at BETWEEN '2026-01-01' AND '2026-01-31';
-- ✅ 理想结果:"Partitions selected: 1 out of 24"(仅扫描了 1 个目标分区)
-- ❌ 糟糕结果:"Partitions selected: 24 out of 24"(全表扫描)

7. 分区维护清单与备份策略

以下操作建议纳入每周/月度巡检:

维护项 执行频率 检查方法
检查分区裁剪是否生效 每次新查询上线前 EXPLAIN ANALYZE 确认 selected partitions 数量
统计分区数量(建议 ≤ 1000) 每月 SELECT count(*) FROM pg_inherits WHERE inhparent = 'parent_table'::regclass;
无索引全分区扫描扫描量监控 每日 query log+dashboard pg_stat_statements 筛选总行数爆炸,跨 10+ 分区的查询
监控过期滞留分区(已 DETACH 但未删除) 每月 pg_class 中 relkind = ‘r’ 且 relname like ‘%_old’
pg_dump 备份同时考虑分区 日常演练 对父表 dump 即可导出全部分区数据

特别提醒:容量规划与分区设计不分家

容量预测能反哺分区设计——例如,如果按天分区一天的写入量就达到 100GB,应考虑切换到按小时分区缩小单个子表大小;如果一周的数据填不满一个 1GB 的块,按季度分区或合并多个小表可能更适合。

写在最后:规划未来的能力

一个优秀的 DBA 评判标准,不在于他能在数据库宕机时多快恢复,而在于他是否在宕机前就已经做好了所有准备——提前 3 个月预测到了磁盘写满的时间,并在预警后的第一个周末完成了在线扩容。

分区策略和容量规划是这种“预防能力”的两根支柱。把分区表视为设计阶段的重要决策,让 pg_partman 跑在 cron 里自动完成每月的分区创建和归档;把容量监控固化每天的巡检脚本里,让数据库的增长变成可预测、可管理的常态。

下一期预告:DBA 的自动化运维工具箱,涵盖自动化巡检、告警收敛、混沌工程,以及借助 AI 诊断查询计划的进阶思路。

参考资料
  • Partitioning at Scale: Range, Hash, and Automated Maintenance – Rockdata & JusDB Team [10†L3-L14]
  • How to Automate PostgreSQL Partitioning with pg_partman – Cybrosys Research, 2025
  • SQL分区表索引策略_本地索引与全局索引对比 – php.cn, 2026
  • PostgreSQL分区表性能优化实战手册(附压测对比) – Alibaba Cloud Developer
  • postgresql历史数据如何归档最优_postgresql归档管理方案 – php.cn
  • postgresql磁盘占用如何持续预测_postgresql容量规划体系 – php.cn
  • 数据库容量规划常见误区:90%DBA都踩过的5个坑 – CSDN, 2025

Star
Donate
PostgreSQL 运维实战系列,第四期:故障排查与深度诊断实战
Previous
PostgreSQL 运维实战系列,第六期:DBA 的自动化运维与 AI 赋能工具箱
Next

Leave a comment

Registration is not required

Clyde Jin
303 Articles
0 Comments
0 Like
Recent Posts

HiddenMerit Daily · Issue 60

📊 HiddenMerit Daily · Issue 60 Focus on Database Frontiers, Practical Insights for DBAs July 22, 2026 | 5 Selected Global Breaking News 01|Oracle Releases Largest Quarterly Patch in History: 1,449 Patches Fix 1,235 CVEs, 261 Critical On July 21, Oracle released its July 2026 Critical Patch Update (CPU), setting a record for the largest single patch release in the company’s history. This CPU contains 1,449 security patches fixing 1,235 independent CVEs across 32 Oracle product families, of which 261 patches are rated Critical. Patch Distribution by Product Family: Product Family Patches Remotely Exploitable Without Authentication Oracle E‑Business Suite 410 45 Oracle Fusion Middleware 355 219 Oracle Communications 168 122 Oracle MySQL 54 9 Oracle Database Server 15 6 Context for This Patch: Oracle had already issued an urgent “Prepare Now” warning a week earlier, emphasising that AI is fundamentally lowering the barrier to discovering and exploiting vulnerabilities – frontier AI models can analyse software changes, reverse‑engineer security patches, and develop attack paths at unprecedented speed. Oracle has collaborated with state‑of‑the‑art models from Anthropic and OpenAI to proactively identify and fix potential security vulnerabilities. Oracle strongly recommends that customers immediately test and deploy this update in their monthly patch cycles. […]

HiddenMerit Daily · Issue 59

📊 HiddenMerit Daily · Issue 59 Focus on Database Frontiers, Practical Insights for DBAs July 21, 2026 | 5 Selected Global Breaking News 01|Oracle Issues Urgent Warning: July 21 Release Update to Fix Large Number of High‑Risk Vulnerabilities, Immediate Deployment Recommended On July 13, Oracle issued an urgent security warning, strongly recommending that all customers running supported Oracle Database versions (including Oracle Database 19c and Oracle AI Database 26ai) immediately test and deploy the Release Update (RU) after its release on July 21. Background: New frontier AI models are significantly lowering the barrier to discovering and exploiting software vulnerabilities – these models can identify weaknesses, analyse software changes, reverse‑engineer security patches, and develop potential attack paths at unprecedented speed and scale. AI models are also becoming increasingly adept at combining multiple weaknesses across the application and data stack into complex attacks, even when individual weaknesses do not themselves pose a serious risk. As a result, protecting systems solely at the network or application layer is no longer sufficient; enterprises must protect the entire technology stack. Fixes Included in This RU: Oracle has collaborated with state‑of‑the‑art models from Anthropic and OpenAI to proactively identify and fix potential security vulnerabilities. The upcoming […]

HiddenMerit Daily · Issue 58

📊 HiddenMerit Daily · Issue 58 Focus on Database Frontiers, Practical Insights for DBAs July 20, 2026 | 5 Selected Global Breaking News 01|CAICT: Domestic Databases Enter Core System “Deep Water,” AI‑Native Leads New Industry Landscape On July 9, at the 2026 Trustworthy Database Development Conference, CAICT released the “Database Development Research Report (2026).” The report notes that domestic databases have basically completed peripheral system replacement and have officially entered the critical business system breakthrough phase. Key Data: The global database market reached $131.6 billion in 2025 (approximately RMB 894.09 billion). The Chinese database market reached $9.49 billion in 2025 (approximately RMB 64.48 billion), and is expected to reach RMB 97.974 billion by 2028, with a CAGR of 13.06%. The number of domestic database vendors has shrunk from a peak of 167 to 94, with a clear head‑concentration effect and an intensifying “Matthew effect.” AI‑Native Becomes the Main Theme: The report points out that database technology is accelerating its evolution toward the AI‑native direction, and the global database industry is entering a new phase of landscape restructuring. The role of databases is upgrading from “underlying support systems” to “core engines enabling intelligent decision‑making and business innovation.” AI agents are becoming […]

HiddenMerit Daily · Issue 56

📊 HiddenMerit Daily · Issue 56 Focus on Database Frontiers, Practical Insights for DBAs July 6, 2026 | 5 Selected Global Breaking News 01|Kingware Releases Manufacturing Scenario Database Evolution White Paper: SQL Server Replacement Enters “Deep Water” On July 5, CETC Kingware published a technical article titled “Database Evolution in Manufacturing Scenarios: How Kingware Replaces SQL Server,” pointing out that the data surge on industrial shop floors has exceeded the processing capacity of single‑node systems. Traditional database architectures that rely on vertical scaling are facing unprecedented performance challenges. Over the next 1‑3 years, manufacturing enterprises will no longer face only the “choice of replacement,” but must answer the strategic question: “How do we build an autonomous data foundation in the context of de‑IOE?” Three Paradigm Shifts: Hybrid Workloads Become the Norm: The IT architecture of modern factories is shifting from separated OLTP and OLAP to HTAP mode. The same data system must simultaneously handle tens of thousands of device instruction writes per second and minute‑level production report analysis. Distributed Architecture Becomes a Hard Requirement: When a single table exceeds 100 million rows with daily increments exceeding 1 million rows, the index maintenance cost of traditional single‑node databases rises exponentially. Autonomous […]
生成中...
扫描二维码
扫描二维码