mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-28 11:55:03 +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:
		| @@ -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 */ | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user