0001-lazy-btree-scan.patch
text/x-diff
Filename: 0001-lazy-btree-scan.patch
Type: text/x-diff
Part: 0
Patch
Format: format-patch
Series: patch 0001
Subject: lazy btree scan
| File | + | − |
|---|---|---|
| src/backend/access/nbtree/nbtree.c | 59 | 0 |
| src/include/access/nbtree.h | 2 | 0 |
From 5f7f04883b8769f424ff98aff21689e640eb3d94 Mon Sep 17 00:00:00 2001
From: Sokolov Yura <funny.falcon@postgrespro.ru>
Date: Tue, 1 Aug 2017 15:57:40 +0300
Subject: [PATCH] lazy btree scan
---
src/backend/access/nbtree/nbtree.c | 59 ++++++++++++++++++++++++++++++++++++++
src/include/access/nbtree.h | 2 ++
2 files changed, 61 insertions(+)
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index 3dbafdd6fc..4216dbe807 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -18,6 +18,7 @@
*/
#include "postgres.h"
+#include "access/generic_xlog.h"
#include "access/nbtree.h"
#include "access/relscan.h"
#include "access/xlog.h"
@@ -937,6 +938,56 @@ btbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
return stats;
}
+static bool
+btneednocleanup(Relation rel)
+{
+ Buffer metabuf;
+ Page metapg;
+ BTPageOpaque metaopaque;
+ bool need_no_cleanup;
+
+ metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_READ);
+ metapg = BufferGetPage(metabuf);
+ metaopaque = (BTPageOpaque) PageGetSpecialPointer(metapg);
+
+ need_no_cleanup = P_NEED_NO_CLEANUP(metaopaque);
+ _bt_relbuf(rel, metabuf);
+ return need_no_cleanup;
+}
+
+static void
+btsetneednocleanup(Relation rel, bool need_no_cleanup)
+{
+ Buffer metabuf;
+ Page metapg;
+ BTPageOpaque metaopaque;
+
+ metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_WRITE);
+ metapg = BufferGetPage(metabuf);
+ metaopaque = (BTPageOpaque) PageGetSpecialPointer(metapg);
+ if (need_no_cleanup && !P_NEED_NO_CLEANUP(metaopaque))
+ {
+ metaopaque->btpo_flags |= BTP_NEED_NO_CLEANUP;
+ MarkBufferDirtyHint(metabuf, true);
+ }
+ else if (!need_no_cleanup && P_NEED_NO_CLEANUP(metaopaque))
+ {
+ GenericXLogState *state;
+ Page pg;
+ BTPageOpaque opaque;
+ XLogRecPtr recptr;
+ state = GenericXLogStart(rel);
+ pg = GenericXLogRegisterBuffer(state, metabuf, 0);
+ opaque = (BTPageOpaque) PageGetSpecialPointer(pg);
+ opaque->btpo_flags &= ~BTP_NEED_NO_CLEANUP;
+ recptr = GenericXLogFinish(state);
+ PageSetLSN(metapg, recptr);
+ MarkBufferDirty(metabuf);
+ }
+
+ _bt_relbuf(rel, metabuf);
+}
+
/*
* Post-VACUUM cleanup.
*
@@ -960,6 +1011,8 @@ btvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
*/
if (stats == NULL)
{
+ if (btneednocleanup(info->index))
+ return NULL;
stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
btvacuumscan(info, stats, NULL, NULL, 0);
}
@@ -1028,6 +1081,9 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
"_bt_pagedel",
ALLOCSET_DEFAULT_SIZES);
+ /* Reset "need no cleanup" flag */
+ btsetneednocleanup(rel, false);
+
/*
* The outer loop iterates over all index pages except the metapage, in
* physical order (we hope the kernel will cooperate in providing
@@ -1111,6 +1167,9 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
/* update statistics */
stats->num_pages = num_pages;
stats->pages_free = vstate.totFreePages;
+
+ if (stats->pages_deleted == stats->pages_free)
+ btsetneednocleanup(rel, true);
}
/*
diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h
index e6abbec280..69d34cbc71 100644
--- a/src/include/access/nbtree.h
+++ b/src/include/access/nbtree.h
@@ -75,6 +75,7 @@ typedef BTPageOpaqueData *BTPageOpaque;
#define BTP_SPLIT_END (1 << 5) /* rightmost page of split group */
#define BTP_HAS_GARBAGE (1 << 6) /* page has LP_DEAD tuples */
#define BTP_INCOMPLETE_SPLIT (1 << 7) /* right sibling's downlink is missing */
+#define BTP_NEED_NO_CLEANUP (1 << 14) /* tree has dead pages, so cleanup is needed */
/*
* The max allowed value of a cycle ID is a bit less than 64K. This is
@@ -181,6 +182,7 @@ typedef struct BTMetaPageData
#define P_IGNORE(opaque) ((opaque)->btpo_flags & (BTP_DELETED|BTP_HALF_DEAD))
#define P_HAS_GARBAGE(opaque) ((opaque)->btpo_flags & BTP_HAS_GARBAGE)
#define P_INCOMPLETE_SPLIT(opaque) ((opaque)->btpo_flags & BTP_INCOMPLETE_SPLIT)
+#define P_NEED_NO_CLEANUP(opaque) (((opaque)->btpo_flags & BTP_NEED_NO_CLEANUP) != 0)
/*
* Lehman and Yao's algorithm requires a ``high key'' on every non-rightmost
--
2.11.0