我们目前正在对数据库执行(早就该进行) 转换以使用分区。数据库保存了大量带时间戳的记录,其中时间戳有自己的索引。
对于此操作,我们将创建现有表的分区版本,然后将现有表附加为新表的分区。
为了防止在附加分区时锁定,我们将在数据上创建
NOT VALID
约束,然后验证它 - 正如文档中所建议的:
ALTER TABLE foo ADD CONSTRAINT partitioning_constraint
CHECK (record_timestamp BETWEEN '2000-01-01' AND '2024-11-20') -- Last date is several in the future
NOT VALID;
COMMIT;
ALTER TABLE foo VALIDATE CONSTRAINT partitioning_constraint; -- This is taking a very long time reading the data.
奇怪的是,如果我只是简单地搜索与约束不匹配的行,结果几乎立即找不到行:
SELECT * from foo WHERE record_timestamp < '2000-01-01'; -- Instantly returns no rows
SELECT * from foo WHERE record_timestamp > '2000-11-20'; -- Instantly returns no rows
SELECT
证明了它。INVALID
约束证明这不会改变。但是我们需要找到一种方法来验证此约束(或附加为分区)而不读取几 TB 的数据。这是一个生产实例,猛击 IO 确实不是一个选择。
有什么方法可以绕过 postgres 像这样重新读取大量 TB 的数据吗?
不,别无选择。 PostgreSQL 读取整个表并验证所有行。你可以通过操纵目录来作弊,但这既不值得赞扬也不支持。
如果您的系统无法处理大表的单次顺序扫描,那么一旦 autovacuum 开始处理它,您将做什么?
不过,这个约束看起来是错误的。 分区约束总是与下端的
>=
和上端的 <
进行比较,而对于 BETWEEN
,上端与 <=
进行比较。