On Fri, Jun 3, 2016 at 4:24 PM, Kevin Grittner <[email protected]> wrote:
> Consequently, causing the index to be ignored in planning when
> using the old index
That last line should have read "using an old snapshot"
> is not a nice optimization, but necessary for
> correctness. We already have logic to do this for other cases
> (like HOT updates), so it is a matter of tying in to that existing
> code correctly. This won't be all that novel.
Just to demonstrate that, the minimal patch to fix behavior in this
area would be:
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 31a1438..6c379da 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -2268,6 +2268,9 @@ IndexBuildHeapRangeScan(Relation heapRelation,
Assert(numblocks == InvalidBlockNumber);
}
+ if (old_snapshot_threshold >= 0)
+ indexInfo->ii_BrokenHotChain = true;
+
reltuples = 0;
/*
Of course, ii_BrokenHotChain should be renamed to something like
ii_UnsafeForOldSnapshots, and some comments need to be updated; but
the above is the substance of it.
Attached is what I have so far. I'm still looking at what other
comments might need to be adjusted, but thought I should put this
much out for comment now.
--
Kevin Grittner
EDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 31a1438..b072985 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -1672,7 +1672,7 @@ BuildIndexInfo(Relation index)
/* initialize index-build state to default */
ii->ii_Concurrent = false;
- ii->ii_BrokenHotChain = false;
+ ii->ii_UnsafeForOldSnapshots = false;
return ii;
}
@@ -2060,7 +2060,7 @@ index_build(Relation heapRelation,
* about any concurrent readers of the tuple; no other transaction can see
* it yet.
*/
- if (indexInfo->ii_BrokenHotChain && !isreindex &&
+ if (indexInfo->ii_UnsafeForOldSnapshots && !isreindex &&
!indexInfo->ii_Concurrent)
{
Oid indexId = RelationGetRelid(indexRelation);
@@ -2137,11 +2137,11 @@ index_build(Relation heapRelation,
* so here because the AM might reject some of the tuples for its own reasons,
* such as being unable to store NULLs.
*
- * A side effect is to set indexInfo->ii_BrokenHotChain to true if we detect
- * any potentially broken HOT chains. Currently, we set this if there are
- * any RECENTLY_DEAD or DELETE_IN_PROGRESS entries in a HOT chain, without
- * trying very hard to detect whether they're really incompatible with the
- * chain tip.
+ * A side effect is to set indexInfo->ii_UnsafeForOldSnapshots to true if we
+ * detect any potentially broken HOT chains or if old_snapshot_threshold is
+ * set to allow early pruning/vacuuuming. Currently, we set this based on
+ * fairly simple tests; it is not guaranteed that using the index would cause
+ * a problem when set, but if the flag is clear it is guaranteed to be safe.
*/
double
IndexBuildHeapScan(Relation heapRelation,
@@ -2268,6 +2268,14 @@ IndexBuildHeapRangeScan(Relation heapRelation,
Assert(numblocks == InvalidBlockNumber);
}
+ /*
+ * If allowing early pruning/vacuuming, the index cannot be considered
+ * safe for old snapshots, since entries could be missing and lsn is set
+ * to InvalidXLogRecPtr in all pages of the new index.
+ */
+ if (old_snapshot_threshold >= 0)
+ indexInfo->ii_UnsafeForOldSnapshots = true;
+
reltuples = 0;
/*
@@ -2361,7 +2369,7 @@ IndexBuildHeapRangeScan(Relation heapRelation,
{
indexIt = false;
/* mark the index as unsafe for old snapshots */
- indexInfo->ii_BrokenHotChain = true;
+ indexInfo->ii_UnsafeForOldSnapshots = true;
}
else
indexIt = true;
@@ -2488,7 +2496,7 @@ IndexBuildHeapRangeScan(Relation heapRelation,
*/
indexIt = false;
/* mark the index as unsafe for old snapshots */
- indexInfo->ii_BrokenHotChain = true;
+ indexInfo->ii_UnsafeForOldSnapshots = true;
}
else
{
@@ -3409,9 +3417,9 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
!indexForm->indisready ||
!indexForm->indislive);
if (index_bad ||
- (indexForm->indcheckxmin && !indexInfo->ii_BrokenHotChain))
+ (indexForm->indcheckxmin && !indexInfo->ii_UnsafeForOldSnapshots))
{
- if (!indexInfo->ii_BrokenHotChain)
+ if (!indexInfo->ii_UnsafeForOldSnapshots)
indexForm->indcheckxmin = false;
else if (index_bad)
indexForm->indcheckxmin = true;
diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
index 564e10e..8dcac7e 100644
--- a/src/backend/catalog/toasting.c
+++ b/src/backend/catalog/toasting.c
@@ -314,7 +314,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
indexInfo->ii_Unique = true;
indexInfo->ii_ReadyForInserts = true;
indexInfo->ii_Concurrent = false;
- indexInfo->ii_BrokenHotChain = false;
+ indexInfo->ii_UnsafeForOldSnapshots = false;
collationObjectId[0] = InvalidOid;
collationObjectId[1] = InvalidOid;
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index d14d540..a3d8bd2 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -557,7 +557,7 @@ DefineIndex(Oid relationId,
/* In a concurrent build, mark it not-ready-for-inserts */
indexInfo->ii_ReadyForInserts = !stmt->concurrent;
indexInfo->ii_Concurrent = stmt->concurrent;
- indexInfo->ii_BrokenHotChain = false;
+ indexInfo->ii_UnsafeForOldSnapshots = false;
typeObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
collationObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
@@ -761,7 +761,7 @@ DefineIndex(Oid relationId,
indexInfo = BuildIndexInfo(indexRelation);
Assert(!indexInfo->ii_ReadyForInserts);
indexInfo->ii_Concurrent = true;
- indexInfo->ii_BrokenHotChain = false;
+ indexInfo->ii_UnsafeForOldSnapshots = false;
/* Now build the index */
index_build(rel, indexRelation, indexInfo, stmt->primary, false);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index ee4e189..2ba4230 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -49,10 +49,12 @@
* Unique is it a unique index?
* ReadyForInserts is it valid for inserts?
* Concurrent are we doing a concurrent index build?
- * BrokenHotChain did we detect any broken HOT chains?
+ * UnsafeForOldSnapshots did we detect reasons not to use the index with
+ * old snapshots (like broken HOT chains or enabled
+ * early pruning/vacuuming)?
*
- * ii_Concurrent and ii_BrokenHotChain are used only during index build;
- * they're conventionally set to false otherwise.
+ * ii_Concurrent and ii_UnsafeForOldSnapshots are used only during index
+ * build; they're conventionally set to false otherwise.
* ----------------
*/
typedef struct IndexInfo
@@ -73,7 +75,7 @@ typedef struct IndexInfo
bool ii_Unique;
bool ii_ReadyForInserts;
bool ii_Concurrent;
- bool ii_BrokenHotChain;
+ bool ii_UnsafeForOldSnapshots;
} IndexInfo;
/* ----------------
--
Sent via pgsql-committers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-committers