summaryrefslogtreecommitdiff
path: root/src/backend/access/rmgrdesc/gindesc.c
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2014-03-31 15:15:19 +0300
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2014-03-31 15:23:50 +0300
commit14d02f0bb352d70d50106e153aca4af9c4b0b842 (patch)
tree695633a4ebbb4b50da88b43d5cb5a1283018b32f /src/backend/access/rmgrdesc/gindesc.c
parent0cfa34c25a7c8e7017cac346d954016fad0dfc16 (diff)
downloadpostgresql-14d02f0bb352d70d50106e153aca4af9c4b0b842.tar.gz
Rewrite the way GIN posting lists are packed on a page, to reduce WAL volume.
Inserting (in retail) into the new 9.4 format GIN posting tree created much larger WAL records than in 9.3. The previous strategy to WAL logging was basically to log the whole page on each change, with the exception of completely unmodified segments up to the first modified one. That was not too bad when appending to the end of the page, as only the last segment had to be WAL-logged, but per Fujii Masao's testing, even that produced 2x the WAL volume that 9.3 did. The new strategy is to keep track of changes to the posting lists in a more fine-grained fashion, and also make the repacking" code smarter to avoid decoding and re-encoding segments unnecessarily.
Diffstat (limited to 'src/backend/access/rmgrdesc/gindesc.c')
-rw-r--r--src/backend/access/rmgrdesc/gindesc.c65
1 files changed, 59 insertions, 6 deletions
diff --git a/src/backend/access/rmgrdesc/gindesc.c b/src/backend/access/rmgrdesc/gindesc.c
index 1983bcc94c..aa60c8db65 100644
--- a/src/backend/access/rmgrdesc/gindesc.c
+++ b/src/backend/access/rmgrdesc/gindesc.c
@@ -25,6 +25,57 @@ desc_node(StringInfo buf, RelFileNode node, BlockNumber blkno)
node.spcNode, node.dbNode, node.relNode, blkno);
}
+static void
+desc_recompress_leaf(StringInfo buf, ginxlogRecompressDataLeaf *insertData)
+{
+ int i;
+ char *walbuf = ((char *) insertData) + sizeof(ginxlogRecompressDataLeaf);
+
+ appendStringInfo(buf, " %d segments:", (int) insertData->nactions);
+
+ for (i = 0; i < insertData->nactions; i++)
+ {
+ uint8 a_segno = *((uint8 *) (walbuf++));
+ uint8 a_action = *((uint8 *) (walbuf++));
+ uint16 nitems = 0;
+ int newsegsize = 0;
+
+ if (a_action == GIN_SEGMENT_INSERT ||
+ a_action == GIN_SEGMENT_REPLACE)
+ {
+ newsegsize = SizeOfGinPostingList((GinPostingList *) walbuf);
+ walbuf += SHORTALIGN(newsegsize);
+ }
+
+ if (a_action == GIN_SEGMENT_ADDITEMS)
+ {
+ memcpy(&nitems, walbuf, sizeof(uint16));
+ walbuf += sizeof(uint16);
+ walbuf += nitems * sizeof(ItemPointerData);
+ }
+
+ switch(a_action)
+ {
+ case GIN_SEGMENT_ADDITEMS:
+ appendStringInfo(buf, " %d (add %d items)", a_segno, nitems);
+ break;
+ case GIN_SEGMENT_DELETE:
+ appendStringInfo(buf, " %d (delete)", a_segno);
+ break;
+ case GIN_SEGMENT_INSERT:
+ appendStringInfo(buf, " %d (insert)", a_segno);
+ break;
+ case GIN_SEGMENT_REPLACE:
+ appendStringInfo(buf, " %d (replace)", a_segno);
+ break;
+ default:
+ appendStringInfo(buf, " %d unknown action %d ???", a_segno, a_action);
+ /* cannot decode unrecognized actions further */
+ return;
+ }
+ }
+}
+
void
gin_desc(StringInfo buf, uint8 xl_info, char *rec)
{
@@ -70,9 +121,10 @@ gin_desc(StringInfo buf, uint8 xl_info, char *rec)
ginxlogRecompressDataLeaf *insertData =
(ginxlogRecompressDataLeaf *) payload;
- appendStringInfo(buf, " unmodified: %u length: %u (compressed)",
- insertData->unmodifiedsize,
- insertData->length);
+ if (xl_info & XLR_BKP_BLOCK(0))
+ appendStringInfo(buf, " (full page image)");
+ else
+ desc_recompress_leaf(buf, insertData);
}
else
{
@@ -105,9 +157,10 @@ gin_desc(StringInfo buf, uint8 xl_info, char *rec)
ginxlogVacuumDataLeafPage *xlrec = (ginxlogVacuumDataLeafPage *) rec;
appendStringInfoString(buf, "Vacuum data leaf page, ");
desc_node(buf, xlrec->node, xlrec->blkno);
- appendStringInfo(buf, " unmodified: %u length: %u",
- xlrec->data.unmodifiedsize,
- xlrec->data.length);
+ if (xl_info & XLR_BKP_BLOCK(0))
+ appendStringInfo(buf, " (full page image)");
+ else
+ desc_recompress_leaf(buf, &xlrec->data);
}
break;
case XLOG_GIN_DELETE_PAGE: