Commit 059e3614 authored by Tom Lane's avatar Tom Lane

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.
parent 5341cddb
...@@ -2,14 +2,14 @@ ...@@ -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, ...@@ -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, ...@@ -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 @@ ...@@ -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); ...@@ -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) ...@@ -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 @@ ...@@ -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 @@ ...@@ -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); ...@@ -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 */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment