Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit d45e401

Browse files
committed
tableam: Add table_finish_bulk_insert().
This replaces the previous calls of heap_sync() in places using bulk-insert. By passing in the flags used for bulk-insert the AM can decide (first at insert time and then during the finish call) which of the optimizations apply to it, and what operations are necessary to finish a bulk insert operation. Also change HEAP_INSERT_* flags to TABLE_INSERT, and rename hi_options to ti_options. These changes are made even in copy.c, which hasn't yet been converted to tableam. There's no harm in doing so. Author: Andres Freund Discussion: https://postgr.es/m/20180703070645.wchpu5muyto5n647@alap3.anarazel.de
1 parent 26a76cb commit d45e401

File tree

6 files changed

+78
-46
lines changed

6 files changed

+78
-46
lines changed

src/backend/access/heap/heapam_handler.c

+12
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,17 @@ heapam_tuple_lock(Relation relation, ItemPointer tid, Snapshot snapshot,
540540
return result;
541541
}
542542

543+
static void
544+
heapam_finish_bulk_insert(Relation relation, int options)
545+
{
546+
/*
547+
* If we skipped writing WAL, then we need to sync the heap (but not
548+
* indexes since those use WAL anyway / don't go through tableam)
549+
*/
550+
if (options & HEAP_INSERT_SKIP_WAL)
551+
heap_sync(relation);
552+
}
553+
543554

544555
/* ------------------------------------------------------------------------
545556
* DDL related callbacks for heap AM.
@@ -2401,6 +2412,7 @@ static const TableAmRoutine heapam_methods = {
24012412
.tuple_delete = heapam_tuple_delete,
24022413
.tuple_update = heapam_tuple_update,
24032414
.tuple_lock = heapam_tuple_lock,
2415+
.finish_bulk_insert = heapam_finish_bulk_insert,
24042416

24052417
.tuple_fetch_row_version = heapam_fetch_row_version,
24062418
.tuple_get_latest_tid = heap_get_latest_tid,

src/backend/commands/copy.c

+15-20
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ static uint64 CopyTo(CopyState cstate);
319319
static void CopyOneRowTo(CopyState cstate,
320320
Datum *values, bool *nulls);
321321
static void CopyFromInsertBatch(CopyState cstate, EState *estate,
322-
CommandId mycid, int hi_options,
322+
CommandId mycid, int ti_options,
323323
ResultRelInfo *resultRelInfo, TupleTableSlot *myslot,
324324
BulkInsertState bistate,
325325
int nBufferedTuples, HeapTuple *bufferedTuples,
@@ -2328,7 +2328,7 @@ CopyFrom(CopyState cstate)
23282328
PartitionTupleRouting *proute = NULL;
23292329
ErrorContextCallback errcallback;
23302330
CommandId mycid = GetCurrentCommandId(true);
2331-
int hi_options = 0; /* start with default heap_insert options */
2331+
int ti_options = 0; /* start with default table_insert options */
23322332
BulkInsertState bistate;
23332333
CopyInsertMethod insertMethod;
23342334
uint64 processed = 0;
@@ -2392,8 +2392,8 @@ CopyFrom(CopyState cstate)
23922392
* - data is being written to relfilenode created in this transaction
23932393
* then we can skip writing WAL. It's safe because if the transaction
23942394
* doesn't commit, we'll discard the table (or the new relfilenode file).
2395-
* If it does commit, we'll have done the heap_sync at the bottom of this
2396-
* routine first.
2395+
* If it does commit, we'll have done the table_finish_bulk_insert() at
2396+
* the bottom of this routine first.
23972397
*
23982398
* As mentioned in comments in utils/rel.h, the in-same-transaction test
23992399
* is not always set correctly, since in rare cases rd_newRelfilenodeSubid
@@ -2437,9 +2437,9 @@ CopyFrom(CopyState cstate)
24372437
(cstate->rel->rd_createSubid != InvalidSubTransactionId ||
24382438
cstate->rel->rd_newRelfilenodeSubid != InvalidSubTransactionId))
24392439
{
2440-
hi_options |= HEAP_INSERT_SKIP_FSM;
2440+
ti_options |= TABLE_INSERT_SKIP_FSM;
24412441
if (!XLogIsNeeded())
2442-
hi_options |= HEAP_INSERT_SKIP_WAL;
2442+
ti_options |= TABLE_INSERT_SKIP_WAL;
24432443
}
24442444

24452445
/*
@@ -2491,7 +2491,7 @@ CopyFrom(CopyState cstate)
24912491
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
24922492
errmsg("cannot perform FREEZE because the table was not created or truncated in the current subtransaction")));
24932493

2494-
hi_options |= HEAP_INSERT_FROZEN;
2494+
ti_options |= TABLE_INSERT_FROZEN;
24952495
}
24962496

24972497
/*
@@ -2755,7 +2755,7 @@ CopyFrom(CopyState cstate)
27552755
{
27562756
MemoryContext oldcontext;
27572757

2758-
CopyFromInsertBatch(cstate, estate, mycid, hi_options,
2758+
CopyFromInsertBatch(cstate, estate, mycid, ti_options,
27592759
prevResultRelInfo, myslot, bistate,
27602760
nBufferedTuples, bufferedTuples,
27612761
firstBufferedLineNo);
@@ -2978,7 +2978,7 @@ CopyFrom(CopyState cstate)
29782978
if (nBufferedTuples == MAX_BUFFERED_TUPLES ||
29792979
bufferedTuplesSize > 65535)
29802980
{
2981-
CopyFromInsertBatch(cstate, estate, mycid, hi_options,
2981+
CopyFromInsertBatch(cstate, estate, mycid, ti_options,
29822982
resultRelInfo, myslot, bistate,
29832983
nBufferedTuples, bufferedTuples,
29842984
firstBufferedLineNo);
@@ -3015,7 +3015,7 @@ CopyFrom(CopyState cstate)
30153015
{
30163016
tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
30173017
heap_insert(resultRelInfo->ri_RelationDesc, tuple,
3018-
mycid, hi_options, bistate);
3018+
mycid, ti_options, bistate);
30193019
ItemPointerCopy(&tuple->t_self, &slot->tts_tid);
30203020
slot->tts_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
30213021
}
@@ -3050,13 +3050,13 @@ CopyFrom(CopyState cstate)
30503050
{
30513051
if (insertMethod == CIM_MULTI_CONDITIONAL)
30523052
{
3053-
CopyFromInsertBatch(cstate, estate, mycid, hi_options,
3053+
CopyFromInsertBatch(cstate, estate, mycid, ti_options,
30543054
prevResultRelInfo, myslot, bistate,
30553055
nBufferedTuples, bufferedTuples,
30563056
firstBufferedLineNo);
30573057
}
30583058
else
3059-
CopyFromInsertBatch(cstate, estate, mycid, hi_options,
3059+
CopyFromInsertBatch(cstate, estate, mycid, ti_options,
30603060
resultRelInfo, myslot, bistate,
30613061
nBufferedTuples, bufferedTuples,
30623062
firstBufferedLineNo);
@@ -3106,12 +3106,7 @@ CopyFrom(CopyState cstate)
31063106

31073107
FreeExecutorState(estate);
31083108

3109-
/*
3110-
* If we skipped writing WAL, then we need to sync the heap (but not
3111-
* indexes since those use WAL anyway)
3112-
*/
3113-
if (hi_options & HEAP_INSERT_SKIP_WAL)
3114-
heap_sync(cstate->rel);
3109+
table_finish_bulk_insert(cstate->rel, ti_options);
31153110

31163111
return processed;
31173112
}
@@ -3123,7 +3118,7 @@ CopyFrom(CopyState cstate)
31233118
*/
31243119
static void
31253120
CopyFromInsertBatch(CopyState cstate, EState *estate, CommandId mycid,
3126-
int hi_options, ResultRelInfo *resultRelInfo,
3121+
int ti_options, ResultRelInfo *resultRelInfo,
31273122
TupleTableSlot *myslot, BulkInsertState bistate,
31283123
int nBufferedTuples, HeapTuple *bufferedTuples,
31293124
uint64 firstBufferedLineNo)
@@ -3149,7 +3144,7 @@ CopyFromInsertBatch(CopyState cstate, EState *estate, CommandId mycid,
31493144
bufferedTuples,
31503145
nBufferedTuples,
31513146
mycid,
3152-
hi_options,
3147+
ti_options,
31533148
bistate);
31543149
MemoryContextSwitchTo(oldcontext);
31553150

src/backend/commands/createas.c

+6-8
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727
#include "access/heapam.h"
2828
#include "access/reloptions.h"
2929
#include "access/htup_details.h"
30-
#include "access/tableam.h"
3130
#include "access/sysattr.h"
31+
#include "access/tableam.h"
3232
#include "access/xact.h"
3333
#include "access/xlog.h"
3434
#include "catalog/namespace.h"
@@ -60,7 +60,7 @@ typedef struct
6060
Relation rel; /* relation to write to */
6161
ObjectAddress reladdr; /* address of rel, for ExecCreateTableAs */
6262
CommandId output_cid; /* cmin to insert in output tuples */
63-
int hi_options; /* heap_insert performance options */
63+
int ti_options; /* table_insert performance options */
6464
BulkInsertState bistate; /* bulk insert state */
6565
} DR_intorel;
6666

@@ -558,8 +558,8 @@ intorel_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
558558
* We can skip WAL-logging the insertions, unless PITR or streaming
559559
* replication is in use. We can skip the FSM in any case.
560560
*/
561-
myState->hi_options = HEAP_INSERT_SKIP_FSM |
562-
(XLogIsNeeded() ? 0 : HEAP_INSERT_SKIP_WAL);
561+
myState->ti_options = TABLE_INSERT_SKIP_FSM |
562+
(XLogIsNeeded() ? 0 : TABLE_INSERT_SKIP_WAL);
563563
myState->bistate = GetBulkInsertState();
564564

565565
/* Not using WAL requires smgr_targblock be initially invalid */
@@ -586,7 +586,7 @@ intorel_receive(TupleTableSlot *slot, DestReceiver *self)
586586
table_insert(myState->rel,
587587
slot,
588588
myState->output_cid,
589-
myState->hi_options,
589+
myState->ti_options,
590590
myState->bistate);
591591

592592
/* We know this is a newly created relation, so there are no indexes */
@@ -604,9 +604,7 @@ intorel_shutdown(DestReceiver *self)
604604

605605
FreeBulkInsertState(myState->bistate);
606606

607-
/* If we skipped using WAL, must heap_sync before commit */
608-
if (myState->hi_options & HEAP_INSERT_SKIP_WAL)
609-
heap_sync(myState->rel);
607+
table_finish_bulk_insert(myState->rel, myState->ti_options);
610608

611609
/* close rel, but keep lock until commit */
612610
table_close(myState->rel, NoLock);

src/backend/commands/matview.c

+7-8
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "access/heapam.h"
1919
#include "access/htup_details.h"
2020
#include "access/multixact.h"
21+
#include "access/tableam.h"
2122
#include "access/xact.h"
2223
#include "access/xlog.h"
2324
#include "catalog/catalog.h"
@@ -53,7 +54,7 @@ typedef struct
5354
/* These fields are filled by transientrel_startup: */
5455
Relation transientrel; /* relation to write to */
5556
CommandId output_cid; /* cmin to insert in output tuples */
56-
int hi_options; /* heap_insert performance options */
57+
int ti_options; /* table_insert performance options */
5758
BulkInsertState bistate; /* bulk insert state */
5859
} DR_transientrel;
5960

@@ -257,7 +258,7 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
257258
* as open scans.
258259
*
259260
* NB: We count on this to protect us against problems with refreshing the
260-
* data using HEAP_INSERT_FROZEN.
261+
* data using TABLE_INSERT_FROZEN.
261262
*/
262263
CheckTableNotInUse(matviewRel, "REFRESH MATERIALIZED VIEW");
263264

@@ -461,9 +462,9 @@ transientrel_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
461462
* We can skip WAL-logging the insertions, unless PITR or streaming
462463
* replication is in use. We can skip the FSM in any case.
463464
*/
464-
myState->hi_options = HEAP_INSERT_SKIP_FSM | HEAP_INSERT_FROZEN;
465+
myState->ti_options = TABLE_INSERT_SKIP_FSM | TABLE_INSERT_FROZEN;
465466
if (!XLogIsNeeded())
466-
myState->hi_options |= HEAP_INSERT_SKIP_WAL;
467+
myState->ti_options |= TABLE_INSERT_SKIP_WAL;
467468
myState->bistate = GetBulkInsertState();
468469

469470
/* Not using WAL requires smgr_targblock be initially invalid */
@@ -490,7 +491,7 @@ transientrel_receive(TupleTableSlot *slot, DestReceiver *self)
490491
table_insert(myState->transientrel,
491492
slot,
492493
myState->output_cid,
493-
myState->hi_options,
494+
myState->ti_options,
494495
myState->bistate);
495496

496497
/* We know this is a newly created relation, so there are no indexes */
@@ -508,9 +509,7 @@ transientrel_shutdown(DestReceiver *self)
508509

509510
FreeBulkInsertState(myState->bistate);
510511

511-
/* If we skipped using WAL, must heap_sync before commit */
512-
if (myState->hi_options & HEAP_INSERT_SKIP_WAL)
513-
heap_sync(myState->transientrel);
512+
table_finish_bulk_insert(myState->transientrel, myState->ti_options);
514513

515514
/* close transientrel, but keep lock until commit */
516515
table_close(myState->transientrel, NoLock);

src/backend/commands/tablecmds.c

+7-9
Original file line numberDiff line numberDiff line change
@@ -4687,7 +4687,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
46874687
EState *estate;
46884688
CommandId mycid;
46894689
BulkInsertState bistate;
4690-
int hi_options;
4690+
int ti_options;
46914691
ExprState *partqualstate = NULL;
46924692

46934693
/*
@@ -4704,7 +4704,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
47044704
newrel = NULL;
47054705

47064706
/*
4707-
* Prepare a BulkInsertState and options for heap_insert. Because we're
4707+
* Prepare a BulkInsertState and options for table_insert. Because we're
47084708
* building a new heap, we can skip WAL-logging and fsync it to disk at
47094709
* the end instead (unless WAL-logging is required for archiving or
47104710
* streaming replication). The FSM is empty too, so don't bother using it.
@@ -4714,16 +4714,16 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
47144714
mycid = GetCurrentCommandId(true);
47154715
bistate = GetBulkInsertState();
47164716

4717-
hi_options = HEAP_INSERT_SKIP_FSM;
4717+
ti_options = TABLE_INSERT_SKIP_FSM;
47184718
if (!XLogIsNeeded())
4719-
hi_options |= HEAP_INSERT_SKIP_WAL;
4719+
ti_options |= TABLE_INSERT_SKIP_WAL;
47204720
}
47214721
else
47224722
{
47234723
/* keep compiler quiet about using these uninitialized */
47244724
mycid = 0;
47254725
bistate = NULL;
4726-
hi_options = 0;
4726+
ti_options = 0;
47274727
}
47284728

47294729
/*
@@ -4977,7 +4977,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
49774977

49784978
/* Write the tuple out to the new relation */
49794979
if (newrel)
4980-
table_insert(newrel, insertslot, mycid, hi_options, bistate);
4980+
table_insert(newrel, insertslot, mycid, ti_options, bistate);
49814981

49824982
ResetExprContext(econtext);
49834983

@@ -5000,9 +5000,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
50005000
{
50015001
FreeBulkInsertState(bistate);
50025002

5003-
/* If we skipped writing WAL, then we need to sync the heap. */
5004-
if (hi_options & HEAP_INSERT_SKIP_WAL)
5005-
heap_sync(newrel);
5003+
table_finish_bulk_insert(newrel, ti_options);
50065004

50075005
table_close(newrel, NoLock);
50085006
}

src/include/access/tableam.h

+31-1
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,21 @@ typedef struct TableAmRoutine
380380
uint8 flags,
381381
TM_FailureData *tmfd);
382382

383+
/*
384+
* Perform operations necessary to complete insertions made via
385+
* tuple_insert and multi_insert with a BulkInsertState specified. This
386+
* e.g. may e.g. used to flush the relation when inserting with
387+
* TABLE_INSERT_SKIP_WAL specified.
388+
*
389+
* Typically callers of tuple_insert and multi_insert will just pass all
390+
* the flags the apply to them, and each AM has to decide which of them
391+
* make sense for it, and then only take actions in finish_bulk_insert
392+
* that make sense for a specific AM.
393+
*
394+
* Optional callback.
395+
*/
396+
void (*finish_bulk_insert) (Relation rel, int options);
397+
383398

384399
/* ------------------------------------------------------------------------
385400
* DDL related functionality.
@@ -1011,7 +1026,8 @@ table_compute_xid_horizon_for_tuples(Relation rel,
10111026
*
10121027
*
10131028
* The BulkInsertState object (if any; bistate can be NULL for default
1014-
* behavior) is also just passed through to RelationGetBufferForTuple.
1029+
* behavior) is also just passed through to RelationGetBufferForTuple. If
1030+
* `bistate` is provided, table_finish_bulk_insert() needs to be called.
10151031
*
10161032
* On return the slot's tts_tid and tts_tableOid are updated to reflect the
10171033
* insertion. But note that any toasting of fields within the slot is NOT
@@ -1185,6 +1201,20 @@ table_lock_tuple(Relation rel, ItemPointer tid, Snapshot snapshot,
11851201
flags, tmfd);
11861202
}
11871203

1204+
/*
1205+
* Perform operations necessary to complete insertions made via
1206+
* tuple_insert and multi_insert with a BulkInsertState specified. This
1207+
* e.g. may e.g. used to flush the relation when inserting with
1208+
* TABLE_INSERT_SKIP_WAL specified.
1209+
*/
1210+
static inline void
1211+
table_finish_bulk_insert(Relation rel, int options)
1212+
{
1213+
/* optional callback */
1214+
if (rel->rd_tableam && rel->rd_tableam->finish_bulk_insert)
1215+
rel->rd_tableam->finish_bulk_insert(rel, options);
1216+
}
1217+
11881218

11891219
/* ------------------------------------------------------------------------
11901220
* DDL related functionality.

0 commit comments

Comments
 (0)