Commit d3b1b1f9 authored by Tom Lane's avatar Tom Lane

Fix CREATE INDEX CONCURRENTLY so that it won't use synchronized scan for

its second pass over the table.  It has to start at block zero, else the
"merge join" logic for detecting which TIDs are already in the index
doesn't work.  Hence, extend heapam.c's API so that callers can enable or
disable syncscan.  (I put in an option to disable buffer access strategy,
too, just in case somebody needs it.)  Per report from Hannes Dorbath.
parent 689d02a2
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.247 2008/01/01 19:45:46 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.248 2008/01/14 01:39:09 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -62,6 +62,7 @@ ...@@ -62,6 +62,7 @@
static HeapScanDesc heap_beginscan_internal(Relation relation, static HeapScanDesc heap_beginscan_internal(Relation relation,
Snapshot snapshot, Snapshot snapshot,
int nkeys, ScanKey key, int nkeys, ScanKey key,
bool allow_strat, bool allow_sync,
bool is_bitmapscan); bool is_bitmapscan);
static XLogRecPtr log_heap_update(Relation reln, Buffer oldbuf, static XLogRecPtr log_heap_update(Relation reln, Buffer oldbuf,
ItemPointerData from, Buffer newbuf, HeapTuple newtup, bool move); ItemPointerData from, Buffer newbuf, HeapTuple newtup, bool move);
...@@ -81,6 +82,9 @@ static bool HeapSatisfiesHOTUpdate(Relation relation, Bitmapset *hot_attrs, ...@@ -81,6 +82,9 @@ static bool HeapSatisfiesHOTUpdate(Relation relation, Bitmapset *hot_attrs,
static void static void
initscan(HeapScanDesc scan, ScanKey key) initscan(HeapScanDesc scan, ScanKey key)
{ {
bool allow_strat;
bool allow_sync;
/* /*
* Determine the number of blocks we have to scan. * Determine the number of blocks we have to scan.
* *
...@@ -99,25 +103,39 @@ initscan(HeapScanDesc scan, ScanKey key) ...@@ -99,25 +103,39 @@ initscan(HeapScanDesc scan, ScanKey key)
* strategy and enable synchronized scanning (see syncscan.c). Although * strategy and enable synchronized scanning (see syncscan.c). Although
* the thresholds for these features could be different, we make them the * the thresholds for these features could be different, we make them the
* same so that there are only two behaviors to tune rather than four. * same so that there are only two behaviors to tune rather than four.
* (However, some callers need to be able to disable one or both of
* these behaviors, independently of the size of the table.)
* *
* During a rescan, don't make a new strategy object if we don't have to. * During a rescan, don't make a new strategy object if we don't have to.
*/ */
if (!scan->rs_bitmapscan && if (!scan->rs_rd->rd_istemp &&
!scan->rs_rd->rd_istemp &&
scan->rs_nblocks > NBuffers / 4) scan->rs_nblocks > NBuffers / 4)
{
allow_strat = scan->rs_allow_strat;
allow_sync = scan->rs_allow_sync;
}
else
allow_strat = allow_sync = false;
if (allow_strat)
{ {
if (scan->rs_strategy == NULL) if (scan->rs_strategy == NULL)
scan->rs_strategy = GetAccessStrategy(BAS_BULKREAD); scan->rs_strategy = GetAccessStrategy(BAS_BULKREAD);
scan->rs_syncscan = true;
scan->rs_startblock = ss_get_location(scan->rs_rd, scan->rs_nblocks);
} }
else else
{ {
if (scan->rs_strategy != NULL) if (scan->rs_strategy != NULL)
FreeAccessStrategy(scan->rs_strategy); FreeAccessStrategy(scan->rs_strategy);
scan->rs_strategy = NULL; scan->rs_strategy = NULL;
}
if (allow_sync)
{
scan->rs_syncscan = true;
scan->rs_startblock = ss_get_location(scan->rs_rd, scan->rs_nblocks);
}
else
{
scan->rs_syncscan = false; scan->rs_syncscan = false;
scan->rs_startblock = 0; scan->rs_startblock = 0;
} }
...@@ -1058,29 +1076,47 @@ heap_openrv(const RangeVar *relation, LOCKMODE lockmode) ...@@ -1058,29 +1076,47 @@ heap_openrv(const RangeVar *relation, LOCKMODE lockmode)
/* ---------------- /* ----------------
* heap_beginscan - begin relation scan * heap_beginscan - begin relation scan
* *
* heap_beginscan_bm is an alternative entry point for setting up a HeapScanDesc * heap_beginscan_strat offers an extended API that lets the caller control
* for a bitmap heap scan. Although that scan technology is really quite * whether a nondefault buffer access strategy can be used, and whether
* unlike a standard seqscan, there is just enough commonality to make it * syncscan can be chosen (possibly resulting in the scan not starting from
* worth using the same data structure. * block zero). Both of these default to TRUE with plain heap_beginscan.
*
* heap_beginscan_bm is an alternative entry point for setting up a
* HeapScanDesc for a bitmap heap scan. Although that scan technology is
* really quite unlike a standard seqscan, there is just enough commonality
* to make it worth using the same data structure.
* ---------------- * ----------------
*/ */
HeapScanDesc HeapScanDesc
heap_beginscan(Relation relation, Snapshot snapshot, heap_beginscan(Relation relation, Snapshot snapshot,
int nkeys, ScanKey key) int nkeys, ScanKey key)
{ {
return heap_beginscan_internal(relation, snapshot, nkeys, key, false); return heap_beginscan_internal(relation, snapshot, nkeys, key,
true, true, false);
}
HeapScanDesc
heap_beginscan_strat(Relation relation, Snapshot snapshot,
int nkeys, ScanKey key,
bool allow_strat, bool allow_sync)
{
return heap_beginscan_internal(relation, snapshot, nkeys, key,
allow_strat, allow_sync, false);
} }
HeapScanDesc HeapScanDesc
heap_beginscan_bm(Relation relation, Snapshot snapshot, heap_beginscan_bm(Relation relation, Snapshot snapshot,
int nkeys, ScanKey key) int nkeys, ScanKey key)
{ {
return heap_beginscan_internal(relation, snapshot, nkeys, key, true); return heap_beginscan_internal(relation, snapshot, nkeys, key,
false, false, true);
} }
static HeapScanDesc static HeapScanDesc
heap_beginscan_internal(Relation relation, Snapshot snapshot, heap_beginscan_internal(Relation relation, Snapshot snapshot,
int nkeys, ScanKey key, bool is_bitmapscan) int nkeys, ScanKey key,
bool allow_strat, bool allow_sync,
bool is_bitmapscan)
{ {
HeapScanDesc scan; HeapScanDesc scan;
...@@ -1103,6 +1139,8 @@ heap_beginscan_internal(Relation relation, Snapshot snapshot, ...@@ -1103,6 +1139,8 @@ heap_beginscan_internal(Relation relation, Snapshot snapshot,
scan->rs_nkeys = nkeys; scan->rs_nkeys = nkeys;
scan->rs_bitmapscan = is_bitmapscan; scan->rs_bitmapscan = is_bitmapscan;
scan->rs_strategy = NULL; /* set in initscan */ scan->rs_strategy = NULL; /* set in initscan */
scan->rs_allow_strat = allow_strat;
scan->rs_allow_sync = allow_sync;
/* /*
* we can use page-at-a-time mode if it's an MVCC-safe snapshot * we can use page-at-a-time mode if it's an MVCC-safe snapshot
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.290 2008/01/03 21:23:15 tgl Exp $ * $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.291 2008/01/14 01:39:09 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -2004,12 +2004,16 @@ validate_index_heapscan(Relation heapRelation, ...@@ -2004,12 +2004,16 @@ validate_index_heapscan(Relation heapRelation,
/* /*
* Prepare for scan of the base relation. We need just those tuples * Prepare for scan of the base relation. We need just those tuples
* satisfying the passed-in reference snapshot. * satisfying the passed-in reference snapshot. We must disable syncscan
*/ * here, because it's critical that we read from block zero forward to
scan = heap_beginscan(heapRelation, /* relation */ * match the sorted TIDs.
snapshot, /* seeself */ */
0, /* number of keys */ scan = heap_beginscan_strat(heapRelation, /* relation */
NULL); /* scan key */ snapshot, /* snapshot */
0, /* number of keys */
NULL, /* scan key */
true, /* buffer access strategy OK */
false); /* syncscan not OK */
/* /*
* Scan all tuples matching the snapshot. * Scan all tuples matching the snapshot.
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.129 2008/01/01 19:45:56 momjian Exp $ * $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.130 2008/01/14 01:39:09 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -141,6 +141,9 @@ extern Relation heap_openrv(const RangeVar *relation, LOCKMODE lockmode); ...@@ -141,6 +141,9 @@ extern Relation heap_openrv(const RangeVar *relation, LOCKMODE lockmode);
extern HeapScanDesc heap_beginscan(Relation relation, Snapshot snapshot, extern HeapScanDesc heap_beginscan(Relation relation, Snapshot snapshot,
int nkeys, ScanKey key); int nkeys, ScanKey key);
extern HeapScanDesc heap_beginscan_strat(Relation relation, Snapshot snapshot,
int nkeys, ScanKey key,
bool allow_strat, bool allow_sync);
extern HeapScanDesc heap_beginscan_bm(Relation relation, Snapshot snapshot, extern HeapScanDesc heap_beginscan_bm(Relation relation, Snapshot snapshot,
int nkeys, ScanKey key); int nkeys, ScanKey key);
extern void heap_rescan(HeapScanDesc scan, ScanKey key); extern void heap_rescan(HeapScanDesc scan, ScanKey key);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.59 2008/01/01 19:45:56 momjian Exp $ * $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.60 2008/01/14 01:39:09 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -28,6 +28,8 @@ typedef struct HeapScanDescData ...@@ -28,6 +28,8 @@ typedef struct HeapScanDescData
ScanKey rs_key; /* array of scan key descriptors */ ScanKey rs_key; /* array of scan key descriptors */
bool rs_bitmapscan; /* true if this is really a bitmap scan */ bool rs_bitmapscan; /* true if this is really a bitmap scan */
bool rs_pageatatime; /* verify visibility page-at-a-time? */ bool rs_pageatatime; /* verify visibility page-at-a-time? */
bool rs_allow_strat; /* allow or disallow use of access strategy */
bool rs_allow_sync; /* allow or disallow use of syncscan */
/* state set up at initscan time */ /* state set up at initscan time */
BlockNumber rs_nblocks; /* number of blocks to scan */ BlockNumber rs_nblocks; /* number of blocks to scan */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment