*** a/doc/src/sgml/config.sgml
--- b/doc/src/sgml/config.sgml
***************
*** 1162,1167 **** include 'filename'
--- 1162,1183 ----
+
+ gin_fast_limit (integer)
+
+ gin_fast_limit> configuration parameter
+
+
+
+ Specifies the amount of memory to be used by the fastgin cache before writing
+ to the GIN index itself. The value defaults to 128kB.
+ The fastgin cache is more effective when it is small. The size of gin_fast_limit
+ should be kept significantly lower than work_mem. A value of 0 will turn off
+ the cache entirely. This global can be overridden by the index setting fast_cache_size.
+
+
+
+
max_stack_depth (integer)
*** a/doc/src/sgml/ref/create_index.sgml
--- b/doc/src/sgml/ref/create_index.sgml
***************
*** 355,360 **** CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ name
--- 355,373 ----
+
+ FAST_CACHE_SIZE>
+
+
+ This setting controls the size of the fast update cache described in
+ . The parameter describes the size (in kB)
+ of the fast update cache. A value of -1 indicates that the index will
+ use the current global size (gin_fast_limit>). However, if the
+ value is above -1, the index-specific value will be used.
+ The default is -1>.
+
+
+
*** a/src/backend/access/common/reloptions.c
--- b/src/backend/access/common/reloptions.c
***************
*** 177,182 **** static relopt_int intRelOpts[] =
--- 177,189 ----
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
}, -1, 0, 2000000000
},
+ {
+ {
+ "fast_cache_size",
+ "Size of the fast gin cache, in kB",
+ RELOPT_KIND_GIN
+ }, -1, 0, INT_MAX
+ },
/* list terminator */
{{NULL}}
};
*** a/src/backend/access/gin/ginfast.c
--- b/src/backend/access/gin/ginfast.c
***************
*** 28,33 ****
--- 28,40 ----
#define GIN_PAGE_FREESIZE \
( BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - MAXALIGN(sizeof(GinPageOpaqueData)) )
+ #define GET_RELATION_LIMIT(relation) \
+ ((relation)->rd_options ? \
+ ((GinOptions *) (relation)->rd_options)->fastCacheSize : (-1))
+
+ #define HAS_RELATION_LIMIT(relation) \
+ (GET_RELATION_LIMIT(relation) > -1)
+
typedef struct KeyArray
{
Datum *keys; /* expansible array */
***************
*** 426,433 **** ginHeapTupleFastInsert(GinState *ginstate, GinTupleCollector *collector)
*
* ginInsertCleanup() should not be called inside our CRIT_SECTION.
*/
! if (metadata->nPendingPages * GIN_PAGE_FREESIZE > work_mem * 1024L)
needCleanup = true;
UnlockReleaseBuffer(metabuffer);
--- 433,450 ----
*
* ginInsertCleanup() should not be called inside our CRIT_SECTION.
*/
!
! if (HAS_RELATION_LIMIT(index))
! {
! if (metadata->nPendingPages * GIN_PAGE_FREESIZE > GET_RELATION_LIMIT(index) * 1024L)
! {
! needCleanup = true;
! }
! }
! else if (metadata->nPendingPages * GIN_PAGE_FREESIZE > gin_fast_limit * 1024L)
! {
needCleanup = true;
+ }
UnlockReleaseBuffer(metabuffer);
*** a/src/backend/access/gin/gininsert.c
--- b/src/backend/access/gin/gininsert.c
***************
*** 586,591 **** gininsert(PG_FUNCTION_ARGS)
--- 586,592 ----
if (GinGetUseFastUpdate(index))
{
+ // elog(NOTICE, "using fast update");
GinTupleCollector collector;
memset(&collector, 0, sizeof(GinTupleCollector));
***************
*** 600,605 **** gininsert(PG_FUNCTION_ARGS)
--- 601,607 ----
}
else
{
+ // elog(NOTICE, "not using fast update");
for (i = 0; i < ginstate.origTupdesc->natts; i++)
ginHeapTupleInsert(&ginstate, (OffsetNumber) (i + 1),
values[i], isnull[i],
*** a/src/backend/access/gin/ginutil.c
--- b/src/backend/access/gin/ginutil.c
***************
*** 501,507 **** ginoptions(PG_FUNCTION_ARGS)
GinOptions *rdopts;
int numoptions;
static const relopt_parse_elt tab[] = {
! {"fastupdate", RELOPT_TYPE_BOOL, offsetof(GinOptions, useFastUpdate)}
};
options = parseRelOptions(reloptions, validate, RELOPT_KIND_GIN,
--- 501,508 ----
GinOptions *rdopts;
int numoptions;
static const relopt_parse_elt tab[] = {
! {"fastupdate", RELOPT_TYPE_BOOL, offsetof(GinOptions, useFastUpdate)},
! {"fast_cache_size", RELOPT_TYPE_INT, offsetof(GinOptions, fastCacheSize)}
};
options = parseRelOptions(reloptions, validate, RELOPT_KIND_GIN,
***************
*** 599,601 **** ginUpdateStats(Relation index, const GinStatsData *stats)
--- 600,640 ----
END_CRIT_SECTION();
}
+
+ /*
+ * Used to check if the gin fast cache should be used.
+ * Use the gin_fast_limit global to turn off the cache entirely.
+ * The per-index sizes will kick in if the user has set a size and enabled fastCacheSize
+ */
+ bool
+ GinGetUseFastUpdate(Relation relation)
+ {
+ if((relation)->rd_options)
+ {
+ if( ((GinOptions *) (relation)->rd_options)->fastCacheSize > 0
+ && ((GinOptions *) (relation)->rd_options)->useFastUpdate)
+ {
+ return true;
+ }
+ else if(!((GinOptions *) (relation)->rd_options)->useFastUpdate)
+ {
+ return false;
+ }
+ else if(gin_fast_limit > 0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if(gin_fast_limit > 0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
*** a/src/backend/utils/init/globals.c
--- b/src/backend/utils/init/globals.c
***************
*** 99,104 **** int CTimeZone = 0;
--- 99,105 ----
bool enableFsync = true;
bool allowSystemTableMods = false;
int work_mem = 1024;
+ int gin_fast_limit = 128;
int maintenance_work_mem = 16384;
/*
*** a/src/backend/utils/misc/guc.c
--- b/src/backend/utils/misc/guc.c
***************
*** 1711,1716 **** static struct config_int ConfigureNamesInt[] =
--- 1711,1728 ----
},
{
+ {"gin_fast_limit", PGC_USERSET, RESOURCES_MEM,
+ gettext_noop("Sets the maximum memory to be used for fastgin operations."),
+ gettext_noop("This represents the maximum amount of space stored in "
+ "the fast gin cache."),
+ GUC_UNIT_KB
+ },
+ &gin_fast_limit,
+ 128, 0, MAX_KILOBYTES,
+ NULL, NULL, NULL
+ },
+
+ {
{"maintenance_work_mem", PGC_USERSET, RESOURCES_MEM,
gettext_noop("Sets the maximum memory to be used for maintenance operations."),
gettext_noop("This includes operations such as VACUUM and CREATE INDEX."),
*** a/src/backend/utils/misc/postgresql.conf.sample
--- b/src/backend/utils/misc/postgresql.conf.sample
***************
*** 121,126 ****
--- 121,127 ----
# It is not advisable to set max_prepared_transactions nonzero unless you
# actively intend to use prepared transactions.
#work_mem = 1MB # min 64kB
+ #gin_fast_limit = 128kB # min 0kB
#maintenance_work_mem = 16MB # min 1MB
#max_stack_depth = 2MB # min 100kB
*** a/src/include/access/gin.h
--- b/src/include/access/gin.h
***************
*** 46,52 **** typedef struct GinStatsData
int32 ginVersion;
} GinStatsData;
! /* GUC parameter */
extern PGDLLIMPORT int GinFuzzySearchLimit;
/* ginutil.c */
--- 46,52 ----
int32 ginVersion;
} GinStatsData;
! /* GUC parameters */
extern PGDLLIMPORT int GinFuzzySearchLimit;
/* ginutil.c */
*** a/src/include/access/gin_private.h
--- b/src/include/access/gin_private.h
***************
*** 262,275 **** typedef struct GinOptions
{
int32 vl_len_; /* varlena header (do not touch directly!) */
bool useFastUpdate; /* use fast updates? */
} GinOptions;
- #define GIN_DEFAULT_USE_FASTUPDATE true
- #define GinGetUseFastUpdate(relation) \
- ((relation)->rd_options ? \
- ((GinOptions *) (relation)->rd_options)->useFastUpdate : GIN_DEFAULT_USE_FASTUPDATE)
-
-
/* Macros for buffer lock/unlock operations */
#define GIN_UNLOCK BUFFER_LOCK_UNLOCK
#define GIN_SHARE BUFFER_LOCK_SHARE
--- 262,270 ----
{
int32 vl_len_; /* varlena header (do not touch directly!) */
bool useFastUpdate; /* use fast updates? */
+ int32 fastCacheSize; /* cachesize - independent of work_mem */
} GinOptions;
/* Macros for buffer lock/unlock operations */
#define GIN_UNLOCK BUFFER_LOCK_UNLOCK
#define GIN_SHARE BUFFER_LOCK_SHARE
***************
*** 443,448 **** extern int ginCompareAttEntries(GinState *ginstate,
--- 438,444 ----
extern Datum *ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
Datum value, bool isNull,
int32 *nentries, GinNullCategory **categories);
+ extern bool GinGetUseFastUpdate(Relation relation);
extern OffsetNumber gintuple_get_attrnum(GinState *ginstate, IndexTuple tuple);
extern Datum gintuple_get_key(GinState *ginstate, IndexTuple tuple,
*** a/src/include/miscadmin.h
--- b/src/include/miscadmin.h
***************
*** 230,235 **** extern int CTimeZone;
--- 230,236 ----
extern bool enableFsync;
extern bool allowSystemTableMods;
extern PGDLLIMPORT int work_mem;
+ extern PGDLLIMPORT int gin_fast_limit;
extern PGDLLIMPORT int maintenance_work_mem;
extern int VacuumCostPageHit;