mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
Although we can't support out-of-line TOAST storage in indexes (yet),
compressed storage works perfectly well. Might as well have a coherent strategy for applying it, rather than the haphazard store-what-you-get approach that was in the code before. The strategy I've set up here is to attempt compression of any compressible index value exceeding BLCKSZ/16, or about 500 bytes by default.
This commit is contained in:
parent
5341cddba8
commit
059e361481
@ -2,14 +2,14 @@
|
|||||||
*
|
*
|
||||||
* indextuple.c
|
* indextuple.c
|
||||||
* This file contains index tuple accessor and mutator routines,
|
* This file contains index tuple accessor and mutator routines,
|
||||||
* as well as a few various tuple utilities.
|
* as well as various tuple utilities.
|
||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.50 2001/01/24 19:42:47 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.51 2001/02/15 20:57:01 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -57,25 +57,45 @@ index_formtuple(TupleDesc tupleDescriptor,
|
|||||||
#ifdef TOAST_INDEX_HACK
|
#ifdef TOAST_INDEX_HACK
|
||||||
for (i = 0; i < numberOfAttributes; i++)
|
for (i = 0; i < numberOfAttributes; i++)
|
||||||
{
|
{
|
||||||
if (null[i] != ' ' || tupleDescriptor->attrs[i]->attlen >= 0)
|
Form_pg_attribute att = tupleDescriptor->attrs[i];
|
||||||
|
|
||||||
|
untoasted_value[i] = value[i];
|
||||||
|
untoasted_free[i] = false;
|
||||||
|
|
||||||
|
/* Do nothing if value is NULL or not of varlena type */
|
||||||
|
if (null[i] != ' ' || att->attlen >= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If value is stored EXTERNAL, must fetch it so we are not
|
||||||
|
* depending on outside storage. This should be improved someday.
|
||||||
|
*/
|
||||||
|
if (VARATT_IS_EXTERNAL(value[i]))
|
||||||
{
|
{
|
||||||
untoasted_value[i] = value[i];
|
untoasted_value[i] = PointerGetDatum(
|
||||||
untoasted_free[i] = false;
|
heap_tuple_fetch_attr(
|
||||||
|
(varattrib *) DatumGetPointer(value[i])));
|
||||||
|
untoasted_free[i] = true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
/*
|
||||||
|
* If value is above size target, and is of a compressible datatype,
|
||||||
|
* try to compress it in-line.
|
||||||
|
*/
|
||||||
|
if (VARATT_SIZE(untoasted_value[i]) > TOAST_INDEX_TARGET &&
|
||||||
|
!VARATT_IS_EXTENDED(untoasted_value[i]) &&
|
||||||
|
(att->attstorage == 'x' || att->attstorage == 'm'))
|
||||||
{
|
{
|
||||||
if (VARATT_IS_EXTERNAL(value[i]))
|
Datum cvalue = toast_compress_datum(untoasted_value[i]);
|
||||||
|
|
||||||
|
if (DatumGetPointer(cvalue) != NULL)
|
||||||
{
|
{
|
||||||
untoasted_value[i] = PointerGetDatum(
|
/* successful compression */
|
||||||
heap_tuple_fetch_attr(
|
if (untoasted_free[i])
|
||||||
(varattrib *)DatumGetPointer(value[i])));
|
pfree(DatumGetPointer(untoasted_value[i]));
|
||||||
|
untoasted_value[i] = cvalue;
|
||||||
untoasted_free[i] = true;
|
untoasted_free[i] = true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
untoasted_value[i] = value[i];
|
|
||||||
untoasted_free[i] = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -137,10 +157,9 @@ index_formtuple(TupleDesc tupleDescriptor,
|
|||||||
* Here we make sure that the size will fit in the field reserved for
|
* Here we make sure that the size will fit in the field reserved for
|
||||||
* it in t_info.
|
* it in t_info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((size & INDEX_SIZE_MASK) != size)
|
if ((size & INDEX_SIZE_MASK) != size)
|
||||||
elog(ERROR, "index_formtuple: data takes %lu bytes: too big",
|
elog(ERROR, "index_formtuple: data takes %lu bytes, max is %d",
|
||||||
(unsigned long)size);
|
(unsigned long) size, INDEX_SIZE_MASK);
|
||||||
|
|
||||||
infomask |= size;
|
infomask |= size;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.16 2001/02/09 17:30:03 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.17 2001/02/15 20:57:01 tgl Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
@ -45,7 +45,6 @@ static void toast_delete(Relation rel, HeapTuple oldtup);
|
|||||||
static void toast_delete_datum(Relation rel, Datum value);
|
static void toast_delete_datum(Relation rel, Datum value);
|
||||||
static void toast_insert_or_update(Relation rel, HeapTuple newtup,
|
static void toast_insert_or_update(Relation rel, HeapTuple newtup,
|
||||||
HeapTuple oldtup);
|
HeapTuple oldtup);
|
||||||
static Datum toast_compress_datum(Datum value);
|
|
||||||
static Datum toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value);
|
static Datum toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value);
|
||||||
static varattrib *toast_fetch_datum(varattrib *attr);
|
static varattrib *toast_fetch_datum(varattrib *attr);
|
||||||
|
|
||||||
@ -721,7 +720,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
|||||||
* the tuple!
|
* the tuple!
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
static Datum
|
Datum
|
||||||
toast_compress_datum(Datum value)
|
toast_compress_datum(Datum value)
|
||||||
{
|
{
|
||||||
varattrib *tmp;
|
varattrib *tmp;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000, PostgreSQL Development Team
|
* Copyright (c) 2000, PostgreSQL Development Team
|
||||||
*
|
*
|
||||||
* $Id: tuptoaster.h,v 1.8 2000/08/04 04:16:10 tgl Exp $
|
* $Id: tuptoaster.h,v 1.9 2001/02/15 20:57:01 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -40,6 +40,12 @@
|
|||||||
|
|
||||||
#define TOAST_TUPLE_TARGET (MaxTupleSize / 4)
|
#define TOAST_TUPLE_TARGET (MaxTupleSize / 4)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If an index value is larger than TOAST_INDEX_TARGET, we will try to
|
||||||
|
* compress it (we can't move it out-of-line, however). Note that this
|
||||||
|
* number is per-datum, not per-tuple, for simplicity in index_formtuple().
|
||||||
|
*/
|
||||||
|
#define TOAST_INDEX_TARGET (MaxTupleSize / 16)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When we store an oversize datum externally, we divide it into chunks
|
* When we store an oversize datum externally, we divide it into chunks
|
||||||
@ -95,6 +101,14 @@ extern varattrib *heap_tuple_fetch_attr(varattrib * attr);
|
|||||||
*/
|
*/
|
||||||
extern varattrib *heap_tuple_untoast_attr(varattrib * attr);
|
extern varattrib *heap_tuple_untoast_attr(varattrib * attr);
|
||||||
|
|
||||||
|
/* ----------
|
||||||
|
* toast_compress_datum -
|
||||||
|
*
|
||||||
|
* Create a compressed version of a varlena datum, if possible
|
||||||
|
* ----------
|
||||||
|
*/
|
||||||
|
extern Datum toast_compress_datum(Datum value);
|
||||||
|
|
||||||
#endif /* TUPLE_TOASTER_ACTIVE */
|
#endif /* TUPLE_TOASTER_ACTIVE */
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user