表分区按范围或键拆分数据
范围分区把边界定义变成写入路由规则。PostgreSQL 按键值把行放到能够接受它的分区,无论这条数据准时到达,还是晚了几个月。任何查询获得裁剪收益之前,都需要先定义正确边界、使用匹配的时间类型,并安排缺失范围的处理流程。分区建表成功,只是这些条件中的一部分。 使用相邻的左闭右开范围 范围分区包含下界,不包含上界。九月可以从九月一日开始,一直到十月一日之前;十月正好从同一边界开始,双方不会重叠。不要靠猜测一个月最后可表示的时间戳来定义范围。相邻的左闭右开区间,不依赖时间字段究竟保留多少位小数,也能避免边界遗漏。 查询同样需要准确表达区间。大于等于下界、小于上界的条件,适合描述一个月的数据。BETWEEN 包含两个端点,因此,把下月第一瞬间写成其上界,可能把下个月的数据也查进来。分区路由只能执行数据布局规则,不能替一个请求了错误区间的条件修正业务含义。 分区键类型与时区也是定义的一部分。timestamptz 代表瞬间,不带时区的 timestamp 则代表没有对应时区解释的本地日期时间。示例为每个边界显式写出 UTC 偏移。如果业务月份按另一个时区划分,应根据那个时区的规则推导边界,而不是假定所有本地日期都对应相同的实际时长。 缺失范围是一种运维状态 没有分区接受新键值时,插入会报错,除非 DEFAULT 分区能够接住它。日历进入新月份,并不会让 PostgreSQL 自动创建下一张月表。应在写入需要之前创建范围,同时考虑迟到数据和旧日期修正。输入键不必单调增长,路由照样能够工作;关键是相应目标范围仍然存在。 DEFAULT 可以接收显式范围之外的值,减少立即发生的插入失败,但如果不检查默认表,也会掩盖分区管理遗漏。持续增长的默认分区可能混入多个互不相关的时间范围,让后续整理更困难。应让“有意保留的例外数据”与“忘记创建分区的日常数据”保持可辨认,不能把插入暂时不报错当成管理正常。 新增显式分区,会改变默认分区能够接受的值。如果新范围对应的行还留在 DEFAULT 中,PostgreSQL 会拒绝变更,而不会允许两处同时拥有这批数据。应先把这些行迁移到合适的暂存表或按规则处理,再挂载新分区。边界是被执行的数据规则,不是可以随意标错的说明标签。 坏掉的样子 下一月分区未创建时,部署可能恰好在跨月瞬间出现写入失败。补建分区又可能因为 DEFAULT 已经积累对应行而失败。这两种问题都属于路由和数据位置,不是规划器统计陈旧。应先检查被拒绝的键和当前边界,再决定操作,不能直接运行 ANALYZE 或改索引,希望它们修复缺失范围。 ATTACH 可能扫描候选表以验证边界,也可能检查默认分区中是否存在冲突数据。合适且已验证的约束能省去部分扫描,但操作仍需要锁,并要求表结构兼容。PostgreSQL 十八的 ATTACH 在父表上取得 SHARE UPDATE EXCLUSIVE,在候选表和存在的 DEFAULT 表上取得 ACCESS EXCLUSIVE。省掉验证扫描,并不等于省掉这些取锁要求。活跃表上迁移数据时,需要协调写入者和锁获取;一个隔离环境中的事务示例,不是完整的在线迁移操作方案。 ...