]> granicus.if.org Git - postgresql/commitdiff
Although we can't support out-of-line TOAST storage in indexes (yet),
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 15 Feb 2001 20:57:01 +0000 (20:57 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 15 Feb 2001 20:57:01 +0000 (20:57 +0000)
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.

src/backend/access/common/indextuple.c
src/backend/access/heap/tuptoaster.c
src/include/access/tuptoaster.h

index 16b5233eb3907b2b1ead4dde2175a00a4bf1d6b3..4b46c202dcd47064038267fcbb5f99fb47df8787 100644 (file)
@@ -2,14 +2,14 @@
  *
  * indextuple.c
  *        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) 1994, Regents of the University of California
  *
  *
  * 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
        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_free[i] = false;
+                       untoasted_value[i] = PointerGetDatum(
+                               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(
-                                               heap_tuple_fetch_attr(
-                                               (varattrib *)DatumGetPointer(value[i])));
+                               /* successful compression */
+                               if (untoasted_free[i])
+                                       pfree(DatumGetPointer(untoasted_value[i]));
+                               untoasted_value[i] = cvalue;
                                untoasted_free[i] = true;
                        }
-                       else
-                       {
-                               untoasted_value[i] = value[i];
-                               untoasted_free[i] = false;
-                       }
                }
        }
 #endif
@@ -137,10 +157,9 @@ index_formtuple(TupleDesc tupleDescriptor,
         * Here we make sure that the size will fit in the field reserved for
         * it in t_info.
         */
-
        if ((size & INDEX_SIZE_MASK) != size)
-               elog(ERROR, "index_formtuple: data takes %lu bytes: too big",
-                       (unsigned long)size);
+               elog(ERROR, "index_formtuple: data takes %lu bytes, max is %d",
+                        (unsigned long) size, INDEX_SIZE_MASK);
 
        infomask |= size;
 
index a1497e40f1f0b16bc42fe1c846ff749ece09083a..a3cf6ae7116a7e4dc11eb40752e1dfe74efc9c9f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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
@@ -45,7 +45,6 @@ static void                   toast_delete(Relation rel, HeapTuple oldtup);
 static void                    toast_delete_datum(Relation rel, Datum value);
 static void                    toast_insert_or_update(Relation rel, HeapTuple newtup,
                                                                HeapTuple oldtup);
-static Datum           toast_compress_datum(Datum value);
 static Datum           toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value);
 static varattrib   *toast_fetch_datum(varattrib *attr);
 
@@ -721,7 +720,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
  *     the tuple!
  * ----------
  */
-static Datum
+Datum
 toast_compress_datum(Datum value)
 {
        varattrib          *tmp;
index 23f31aec522572def9504b8c91623880d3d088bd..05c4b2c1e408eb353ec4b997a5d921dca5f9f34f 100644 (file)
@@ -6,7 +6,7 @@
  *
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
 
 #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
@@ -95,6 +101,14 @@ extern varattrib *heap_tuple_fetch_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 */