Thread
-
Support for 8-byte TOAST values, round two
Michael Paquier <michael@paquier.xyz> — 2026-05-08T06:07:13Z
Hi all, This is a follow-up of the previous thread about $subject, with a reworked patch set for discussion in v20, as I care about the subject: https://www.postgresql.org/message-id/aFOnKHG7Wn-Srnpv@paquier.xyz The main feedback of the previous thread is that the previous implementation with its callbacks for each vartag was not liked much, and their were concerns with pointer redirections and performance. This patch set uses what I am calling the "brutal" approach, relying on a vartag_external of a varlena or the atttype of the TOAST relation to decide which external toast pointer we should use. This uses no function pointers, and patches the code to deal with Oid or Oid8 TOAST values where it matters. So, this time, performance cannot really be an issue. The patch set is structured so as all the ground work happens first (most of it comes from the previous patch set, reorganized a bit), and the introduction of the varatt pieces are last, based on the following rules: - A table can use a 8-byte TOAST value with a new reloption, named toast_value_type that can be set to "oid" (default) or "oid8", creating a TOAST table with a value of the assigned type. This includes support for dumps as well as binary upgrades, so as the atttype of the chunk_id of the TOAST table is preserved. A table with a TOAST type assigned cannot be changed to a different type through a VACUUM FULL or a rewrite, as a matter of implementation simplicity. - Renames and cleanup of various areas related to varatt_external, renaming things to use OID. - The 8-byte TOAST values rely on a Oid8, whose value is retrieved from the control file extended by 4 bytes. The code supports wraparound of values so as we don't assign anything between 0 and FirstNormalObjectId for the lower bytes, same way as before. The last patch introduces a new vartag_external and the new varatt_external_oid8, with an Oid8 as value. Well, not exactly, the patch uses two uint32 fields so as the structure is packed without padding, as of: typedef struct varatt_external_oid8 { int32 va_rawsize; uint32 va_extinfo; uint32 va_valueid_lo; uint32 va_valueid_hi; Oid va_toastrelid; } varatt_external_oid8; Note that if applying all the patches except the last one, the code would use an varatt_external_oid with an oid8 TOAST table. This works, the split is to make reviews easier. An oid8 TOAST table always uses a varatt_external_oid8. I have done a lot of back-and-forth in the patch to try to find a good balance between the manipulation of the varlenas in the detoast and compression paths, as well as reorderbuffer.c and amcheck. And I have finished with the attached, which is kind of nice. The last patch has a low footprint: 9 files changed, 537 insertions(+), 208 deletions(-) Happy to discuss about all that at pgconf.dev. This is of course intended for v20, added to the next CF. Thanks, -- Michael