diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/backend/access/gin/gininsert.c | 78 |
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; |
