1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-05 07:21:24 +03:00

Add support for partial TOAST decompression

When asked for a slice of a TOAST entry, decompress enough to return the
slice instead of decompressing the entire object.

For use cases where the slice is at, or near, the beginning of the entry,
this avoids a lot of unnecessary decompression work.

This changes the signature of pglz_decompress() by adding a boolean to
indicate if it's ok for the call to finish before consuming all of the
source or destination buffers.

Author: Paul Ramsey
Reviewed-By: Rafia Sabih, Darafei Praliaskouski, Regina Obe
Discussion: https://postgr.es/m/CACowWR07EDm7Y4m2kbhN_jnys%3DBBf9A6768RyQdKm_%3DNpkcaWg%40mail.gmail.com
This commit is contained in:
Stephen Frost
2019-04-02 12:35:32 -04:00
parent d50d172e51
commit 4d0e994eed
5 changed files with 70 additions and 36 deletions

View File

@ -75,6 +75,7 @@ static struct varlena *toast_fetch_datum(struct varlena *attr);
static struct varlena *toast_fetch_datum_slice(struct varlena *attr,
int32 sliceoffset, int32 length);
static struct varlena *toast_decompress_datum(struct varlena *attr);
static struct varlena *toast_decompress_datum_slice(struct varlena *attr, int32 slicelength);
static int toast_open_indexes(Relation toastrel,
LOCKMODE lock,
Relation **toastidxs,
@ -301,7 +302,11 @@ heap_tuple_untoast_attr_slice(struct varlena *attr,
{
struct varlena *tmp = preslice;
preslice = toast_decompress_datum(tmp);
/* Decompress enough to encompass the slice and the offset */
if (slicelength > 0 && sliceoffset >= 0)
preslice = toast_decompress_datum_slice(tmp, slicelength + sliceoffset);
else
preslice = toast_decompress_datum(tmp);
if (tmp != attr)
pfree(tmp);
@ -2272,13 +2277,42 @@ toast_decompress_datum(struct varlena *attr)
if (pglz_decompress(TOAST_COMPRESS_RAWDATA(attr),
VARSIZE(attr) - TOAST_COMPRESS_HDRSZ,
VARDATA(result),
TOAST_COMPRESS_RAWSIZE(attr)) < 0)
TOAST_COMPRESS_RAWSIZE(attr), true) < 0)
elog(ERROR, "compressed data is corrupted");
return result;
}
/* ----------
* toast_decompress_datum_slice -
*
* Decompress the front of a compressed version of a varlena datum.
* offset handling happens in heap_tuple_untoast_attr_slice.
* Here we just decompress a slice from the front.
*/
static struct varlena *
toast_decompress_datum_slice(struct varlena *attr, int32 slicelength)
{
struct varlena *result;
int32 rawsize;
Assert(VARATT_IS_COMPRESSED(attr));
result = (struct varlena *) palloc(slicelength + VARHDRSZ);
rawsize = pglz_decompress(TOAST_COMPRESS_RAWDATA(attr),
VARSIZE(attr) - TOAST_COMPRESS_HDRSZ,
VARDATA(result),
slicelength, false);
if (rawsize < 0)
elog(ERROR, "compressed data is corrupted");
SET_VARSIZE(result, rawsize + VARHDRSZ);
return result;
}
/* ----------
* toast_open_indexes
*