From 774a78ffe47557313d69c2b27e7d61480a3b9d1f Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Fri, 12 Sep 2014 11:23:59 +0300 Subject: [PATCH] Fix GIN data page split ratio calculation. The code that tried to split a page at 75/25 ratio, when appending to the end of an index, was buggy in two ways. First, there was a silly typo that caused it to just fill the left page as full as possible. But the logic as it was intended wasn't correct either, and would actually have given a ratio closer to 60/40 than 75/25. Gaetano Mendola spotted the typo. Backpatch to 9.4, where this code was added. --- src/backend/access/gin/gindatapage.c | 29 ++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/backend/access/gin/gindatapage.c b/src/backend/access/gin/gindatapage.c index 76e0cb3e19..e2d15a85fe 100644 --- a/src/backend/access/gin/gindatapage.c +++ b/src/backend/access/gin/gindatapage.c @@ -621,9 +621,9 @@ dataPlaceToPageLeaf(GinBtree btree, Buffer buf, GinBtreeStack *stack, /* * Had to split. * - * We already divided the segments between the left and the right - * page. The left page was filled as full as possible, and the rest - * overflowed to the right page. When building a new index, that's + * leafRepackItems already divided the segments between the left and + * the right page. It filled the left page as full as possible, and + * put the rest to the right page. When building a new index, that's * good, because the table is scanned from beginning to end and there * won't be any more insertions to the left page during the build. * This packs the index as tight as possible. But otherwise, split @@ -631,9 +631,10 @@ dataPlaceToPageLeaf(GinBtree btree, Buffer buf, GinBtreeStack *stack, * until they're balanced. * * As a further heuristic, when appending items to the end of the - * page, split 75/25, one the assumption that subsequent insertions - * will probably also go to the end. This packs the index somewhat - * tighter when appending to a table, which is very common. + * page, try make the left page 75% full, one the assumption that + * subsequent insertions will probably also go to the end. This packs + * the index somewhat tighter when appending to a table, which is very + * common. */ if (!btree->isBuild) { @@ -645,14 +646,18 @@ dataPlaceToPageLeaf(GinBtree btree, Buffer buf, GinBtreeStack *stack, if (lastleftinfo->action != GIN_SEGMENT_DELETE) { segsize = SizeOfGinPostingList(lastleftinfo->seg); + + /* + * Note that we check that the right page doesn't become + * more full than the left page even when appending. It's + * possible that we added enough items to make both pages + * more than 75% full. + */ + if ((leaf->lsize - segsize) - (leaf->rsize + segsize) < 0) + break; if (append) { - if ((leaf->lsize - segsize) - (leaf->lsize - segsize) < BLCKSZ / 4) - break; - } - else - { - if ((leaf->lsize - segsize) - (leaf->rsize + segsize) < 0) + if ((leaf->lsize - segsize) < (BLCKSZ * 3) / 4) break; } -- 2.40.0