summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/gin/gininsert.c78
1 files changed, 36 insertions, 42 deletions
diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c
index 61869d9d931..c2b879b2bf6 100644
--- a/src/backend/access/gin/gininsert.c
+++ b/src/backend/access/gin/gininsert.c
@@ -1401,10 +1401,46 @@ GinBufferKeyEquals(GinBuffer *buffer, GinTuple *tup)
* enough TIDs to trim (with values less than "first" TID from the new tuple),
* we do the trim. By enough we mean at least 128 TIDs (mostly an arbitrary
* number).
+ *
+ * We try freezing TIDs at the beginning of the list first, before attempting
+ * to trim the buffer. This may allow trimming the data earlier, reducing the
+ * memory usage and excluding it from the mergesort.
*/
static bool
GinBufferShouldTrim(GinBuffer *buffer, GinTuple *tup)
{
+ /*
+ * Check if the last TID in the current list is frozen. This is the case
+ * when merging non-overlapping lists, e.g. in each parallel worker.
+ */
+ if ((buffer->nitems > 0) &&
+ (ItemPointerCompare(&buffer->items[buffer->nitems - 1],
+ GinTupleGetFirst(tup)) == 0))
+ buffer->nfrozen = buffer->nitems;
+
+ /*
+ * Now find the last TID we know to be frozen, i.e. the last TID right
+ * before the new GIN tuple.
+ *
+ * Start with the first not-yet-frozen tuple, and walk until we find the
+ * first TID that's higher. If we already know the whole list is frozen
+ * (i.e. nfrozen == nitems), this does nothing.
+ *
+ * XXX This might do a binary search for sufficiently long lists, but it
+ * does not seem worth the complexity. Overlapping lists should be rare
+ * common, TID comparisons are cheap, and we should quickly freeze most of
+ * the list.
+ */
+ for (int i = buffer->nfrozen; i < buffer->nitems; i++)
+ {
+ /* Is the TID after the first TID of the new tuple? Can't freeze. */
+ if (ItemPointerCompare(&buffer->items[i],
+ GinTupleGetFirst(tup)) > 0)
+ break;
+
+ buffer->nfrozen++;
+ }
+
/* not enough TIDs to trim (1024 is somewhat arbitrary number) */
if (buffer->nfrozen < 1024)
return false;
@@ -1470,48 +1506,6 @@ GinBufferStoreTuple(GinBuffer *buffer, GinTuple *tup)
buffer->key = (Datum) 0;
}
- /*
- * Try freeze TIDs at the beginning of the list, i.e. exclude them from
- * the mergesort. We can do that with TIDs before the first TID in the new
- * tuple we're about to add into the buffer.
- *
- * We do this incrementally when adding data into the in-memory buffer,
- * and not later (e.g. when hitting a memory limit), because it allows us
- * to skip the frozen data during the mergesort, making it cheaper.
- */
-
- /*
- * Check if the last TID in the current list is frozen. This is the case
- * when merging non-overlapping lists, e.g. in each parallel worker.
- */
- if ((buffer->nitems > 0) &&
- (ItemPointerCompare(&buffer->items[buffer->nitems - 1],
- GinTupleGetFirst(tup)) == 0))
- buffer->nfrozen = buffer->nitems;
-
- /*
- * Now find the last TID we know to be frozen, i.e. the last TID right
- * before the new GIN tuple.
- *
- * Start with the first not-yet-frozen tuple, and walk until we find the
- * first TID that's higher. If we already know the whole list is frozen
- * (i.e. nfrozen == nitems), this does nothing.
- *
- * XXX This might do a binary search for sufficiently long lists, but it
- * does not seem worth the complexity. Overlapping lists should be rare
- * common, TID comparisons are cheap, and we should quickly freeze most of
- * the list.
- */
- for (int i = buffer->nfrozen; i < buffer->nitems; i++)
- {
- /* Is the TID after the first TID of the new tuple? Can't freeze. */
- if (ItemPointerCompare(&buffer->items[i],
- GinTupleGetFirst(tup)) > 0)
- break;
-
- buffer->nfrozen++;
- }
-
/* add the new TIDs into the buffer, combine using merge-sort */
{
int nnew;