Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3fdeb18

Browse files
committed
Clean up code associated with updating pg_class statistics columns
(relpages/reltuples). To do this, create formal support in heapam.c for"overwrite" tuple updates (including xlog replay capability) and use thatinstead of the ad-hoc overwrites we'd been using in VACUUM and CREATE INDEX.Take the responsibility for updating stats during CREATE INDEX out of theindividual index AMs, and do it where it belongs, in catalog/index.c. Asidefrom being more modular, this avoids having to update the same tuple twice insome paths through CREATE INDEX. It's probably not measurably faster, butfor sure it's a lot cleaner than before.
1 parentc1f3943 commit3fdeb18

File tree

17 files changed

+519
-404
lines changed

17 files changed

+519
-404
lines changed

‎doc/src/sgml/indexam.sgml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.10 2006/05/02 22:25:09 tgl Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.11 2006/05/10 23:18:38 tgl Exp $ -->
22

33
<chapter id="indexam">
44
<title>Index Access Method Interface Definition</title>
@@ -144,7 +144,7 @@
144144

145145
<para>
146146
<programlisting>
147-
void
147+
IndexBuildResult *
148148
ambuild (Relation heapRelation,
149149
Relation indexRelation,
150150
IndexInfo *indexInfo);
@@ -155,6 +155,8 @@ ambuild (Relation heapRelation,
155155
in the table. Ordinarily the <function>ambuild</> function will call
156156
<function>IndexBuildHeapScan()</> to scan the table for existing tuples
157157
and compute the keys that need to be inserted into the index.
158+
The function must return a palloc'd struct containing statistics about
159+
the new index.
158160
</para>
159161

160162
<para>

‎src/backend/access/gin/gininsert.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/gin/gininsert.c,v 1.1 2006/05/02 11:28:54 teodor Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/gin/gininsert.c,v 1.2 2006/05/10 23:18:38 tgl Exp $
1212
*-------------------------------------------------------------------------
1313
*/
1414

@@ -242,6 +242,7 @@ ginbuild(PG_FUNCTION_ARGS) {
242242
Relationheap= (Relation)PG_GETARG_POINTER(0);
243243
Relationindex= (Relation)PG_GETARG_POINTER(1);
244244
IndexInfo*indexInfo= (IndexInfo*)PG_GETARG_POINTER(2);
245+
IndexBuildResult*result;
245246
doublereltuples;
246247
GinBuildStatebuildstate;
247248
Bufferbuffer;
@@ -310,10 +311,15 @@ ginbuild(PG_FUNCTION_ARGS) {
310311

311312
MemoryContextDelete(buildstate.tmpCtx);
312313

313-
/* since we just counted the # of tuples, may as well update stats */
314-
IndexCloseAndUpdateStats(heap,reltuples,index,buildstate.indtuples);
314+
/*
315+
* Return statistics
316+
*/
317+
result= (IndexBuildResult*)palloc(sizeof(IndexBuildResult));
318+
319+
result->heap_tuples=reltuples;
320+
result->index_tuples=buildstate.indtuples;
315321

316-
PG_RETURN_VOID();
322+
PG_RETURN_POINTER(result);
317323
}
318324

319325
/*

‎src/backend/access/gist/gist.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.133 2006/05/1009:19:54 teodor Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.134 2006/05/1023:18:38 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -89,6 +89,7 @@ gistbuild(PG_FUNCTION_ARGS)
8989
Relationheap= (Relation)PG_GETARG_POINTER(0);
9090
Relationindex= (Relation)PG_GETARG_POINTER(1);
9191
IndexInfo*indexInfo= (IndexInfo*)PG_GETARG_POINTER(2);
92+
IndexBuildResult*result;
9293
doublereltuples;
9394
GISTBuildStatebuildstate;
9495
Bufferbuffer;
@@ -154,12 +155,17 @@ gistbuild(PG_FUNCTION_ARGS)
154155
/* okay, all heap tuples are indexed */
155156
MemoryContextDelete(buildstate.tmpCtx);
156157

157-
/* since we just counted the # of tuples, may as well update stats */
158-
IndexCloseAndUpdateStats(heap,reltuples,index,buildstate.indtuples);
159-
160158
freeGISTstate(&buildstate.giststate);
161159

162-
PG_RETURN_VOID();
160+
/*
161+
* Return statistics
162+
*/
163+
result= (IndexBuildResult*)palloc(sizeof(IndexBuildResult));
164+
165+
result->heap_tuples=reltuples;
166+
result->index_tuples=buildstate.indtuples;
167+
168+
PG_RETURN_POINTER(result);
163169
}
164170

165171
/*

‎src/backend/access/hash/hash.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.89 2006/05/02 22:25:10 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.90 2006/05/10 23:18:38 tgl Exp $
1212
*
1313
* NOTES
1414
* This file contains only the public interface routines.
@@ -51,6 +51,7 @@ hashbuild(PG_FUNCTION_ARGS)
5151
Relationheap= (Relation)PG_GETARG_POINTER(0);
5252
Relationindex= (Relation)PG_GETARG_POINTER(1);
5353
IndexInfo*indexInfo= (IndexInfo*)PG_GETARG_POINTER(2);
54+
IndexBuildResult*result;
5455
doublereltuples;
5556
HashBuildStatebuildstate;
5657

@@ -72,10 +73,15 @@ hashbuild(PG_FUNCTION_ARGS)
7273
reltuples=IndexBuildHeapScan(heap,index,indexInfo,
7374
hashbuildCallback, (void*)&buildstate);
7475

75-
/* since we just counted the # of tuples, may as well update stats */
76-
IndexCloseAndUpdateStats(heap,reltuples,index,buildstate.indtuples);
76+
/*
77+
* Return statistics
78+
*/
79+
result= (IndexBuildResult*)palloc(sizeof(IndexBuildResult));
7780

78-
PG_RETURN_VOID();
81+
result->heap_tuples=reltuples;
82+
result->index_tuples=buildstate.indtuples;
83+
84+
PG_RETURN_POINTER(result);
7985
}
8086

8187
/*

‎src/backend/access/heap/heapam.c

Lines changed: 154 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.211 2006/03/31 23:32:05 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.212 2006/05/10 23:18:39 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -2673,6 +2673,97 @@ heap_lock_tuple(Relation relation, HeapTuple tuple, Buffer *buffer,
26732673
returnHeapTupleMayBeUpdated;
26742674
}
26752675

2676+
2677+
/*
2678+
* heap_inplace_update - update a tuple "in place" (ie, overwrite it)
2679+
*
2680+
* Overwriting violates both MVCC and transactional safety, so the uses
2681+
* of this function in Postgres are extremely limited. Nonetheless we
2682+
* find some places to use it.
2683+
*
2684+
* The tuple cannot change size, and therefore it's reasonable to assume
2685+
* that its null bitmap (if any) doesn't change either. So we just
2686+
* overwrite the data portion of the tuple without touching the null
2687+
* bitmap or any of the header fields.
2688+
*
2689+
* tuple is an in-memory tuple structure containing the data to be written
2690+
* over the target tuple. Also, tuple->t_self identifies the target tuple.
2691+
*/
2692+
void
2693+
heap_inplace_update(Relationrelation,HeapTupletuple)
2694+
{
2695+
Bufferbuffer;
2696+
Pagepage;
2697+
OffsetNumberoffnum;
2698+
ItemIdlp=NULL;
2699+
HeapTupleHeaderhtup;
2700+
uint32oldlen;
2701+
uint32newlen;
2702+
2703+
buffer=ReadBuffer(relation,ItemPointerGetBlockNumber(&(tuple->t_self)));
2704+
LockBuffer(buffer,BUFFER_LOCK_EXCLUSIVE);
2705+
page= (Page)BufferGetPage(buffer);
2706+
2707+
offnum=ItemPointerGetOffsetNumber(&(tuple->t_self));
2708+
if (PageGetMaxOffsetNumber(page) >=offnum)
2709+
lp=PageGetItemId(page,offnum);
2710+
2711+
if (PageGetMaxOffsetNumber(page)<offnum|| !ItemIdIsUsed(lp))
2712+
elog(ERROR,"heap_inplace_update: invalid lp");
2713+
2714+
htup= (HeapTupleHeader)PageGetItem(page,lp);
2715+
2716+
oldlen=ItemIdGetLength(lp)-htup->t_hoff;
2717+
newlen=tuple->t_len-tuple->t_data->t_hoff;
2718+
if (oldlen!=newlen||htup->t_hoff!=tuple->t_data->t_hoff)
2719+
elog(ERROR,"heap_inplace_update: wrong tuple length");
2720+
2721+
/* NO EREPORT(ERROR) from here till changes are logged */
2722+
START_CRIT_SECTION();
2723+
2724+
memcpy((char*)htup+htup->t_hoff,
2725+
(char*)tuple->t_data+tuple->t_data->t_hoff,
2726+
newlen);
2727+
2728+
MarkBufferDirty(buffer);
2729+
2730+
/* XLOG stuff */
2731+
if (!relation->rd_istemp)
2732+
{
2733+
xl_heap_inplacexlrec;
2734+
XLogRecPtrrecptr;
2735+
XLogRecDatardata[2];
2736+
2737+
xlrec.target.node=relation->rd_node;
2738+
xlrec.target.tid=tuple->t_self;
2739+
2740+
rdata[0].data= (char*)&xlrec;
2741+
rdata[0].len=SizeOfHeapInplace;
2742+
rdata[0].buffer=InvalidBuffer;
2743+
rdata[0].next=&(rdata[1]);
2744+
2745+
rdata[1].data= (char*)htup+htup->t_hoff;
2746+
rdata[1].len=newlen;
2747+
rdata[1].buffer=buffer;
2748+
rdata[1].buffer_std= true;
2749+
rdata[1].next=NULL;
2750+
2751+
recptr=XLogInsert(RM_HEAP_ID,XLOG_HEAP_INPLACE,rdata);
2752+
2753+
PageSetLSN(page,recptr);
2754+
PageSetTLI(page,ThisTimeLineID);
2755+
}
2756+
2757+
END_CRIT_SECTION();
2758+
2759+
UnlockReleaseBuffer(buffer);
2760+
2761+
/* Send out shared cache inval if necessary */
2762+
if (!IsBootstrapProcessingMode())
2763+
CacheInvalidateHeapTuple(relation,tuple);
2764+
}
2765+
2766+
26762767
/* ----------------
26772768
*heap_markpos- mark scan position
26782769
* ----------------
@@ -3329,6 +3420,59 @@ heap_xlog_lock(XLogRecPtr lsn, XLogRecord *record)
33293420
UnlockReleaseBuffer(buffer);
33303421
}
33313422

3423+
staticvoid
3424+
heap_xlog_inplace(XLogRecPtrlsn,XLogRecord*record)
3425+
{
3426+
xl_heap_inplace*xlrec= (xl_heap_inplace*)XLogRecGetData(record);
3427+
Relationreln=XLogOpenRelation(xlrec->target.node);
3428+
Bufferbuffer;
3429+
Pagepage;
3430+
OffsetNumberoffnum;
3431+
ItemIdlp=NULL;
3432+
HeapTupleHeaderhtup;
3433+
uint32oldlen;
3434+
uint32newlen;
3435+
3436+
if (record->xl_info&XLR_BKP_BLOCK_1)
3437+
return;
3438+
3439+
buffer=XLogReadBuffer(reln,
3440+
ItemPointerGetBlockNumber(&(xlrec->target.tid)),
3441+
false);
3442+
if (!BufferIsValid(buffer))
3443+
return;
3444+
page= (Page)BufferGetPage(buffer);
3445+
3446+
if (XLByteLE(lsn,PageGetLSN(page)))/* changes are applied */
3447+
{
3448+
UnlockReleaseBuffer(buffer);
3449+
return;
3450+
}
3451+
3452+
offnum=ItemPointerGetOffsetNumber(&(xlrec->target.tid));
3453+
if (PageGetMaxOffsetNumber(page) >=offnum)
3454+
lp=PageGetItemId(page,offnum);
3455+
3456+
if (PageGetMaxOffsetNumber(page)<offnum|| !ItemIdIsUsed(lp))
3457+
elog(PANIC,"heap_inplace_redo: invalid lp");
3458+
3459+
htup= (HeapTupleHeader)PageGetItem(page,lp);
3460+
3461+
oldlen=ItemIdGetLength(lp)-htup->t_hoff;
3462+
newlen=record->xl_len-SizeOfHeapInplace;
3463+
if (oldlen!=newlen)
3464+
elog(PANIC,"heap_inplace_redo: wrong tuple length");
3465+
3466+
memcpy((char*)htup+htup->t_hoff,
3467+
(char*)xlrec+SizeOfHeapInplace,
3468+
newlen);
3469+
3470+
PageSetLSN(page,lsn);
3471+
PageSetTLI(page,ThisTimeLineID);
3472+
MarkBufferDirty(buffer);
3473+
UnlockReleaseBuffer(buffer);
3474+
}
3475+
33323476
void
33333477
heap_redo(XLogRecPtrlsn,XLogRecord*record)
33343478
{
@@ -3349,6 +3493,8 @@ heap_redo(XLogRecPtr lsn, XLogRecord *record)
33493493
heap_xlog_newpage(lsn,record);
33503494
elseif (info==XLOG_HEAP_LOCK)
33513495
heap_xlog_lock(lsn,record);
3496+
elseif (info==XLOG_HEAP_INPLACE)
3497+
heap_xlog_inplace(lsn,record);
33523498
else
33533499
elog(PANIC,"heap_redo: unknown op code %u",info);
33543500
}
@@ -3442,6 +3588,13 @@ heap_desc(StringInfo buf, uint8 xl_info, char *rec)
34423588
appendStringInfo(buf,"%u ",xlrec->locking_xid);
34433589
out_target(buf,&(xlrec->target));
34443590
}
3591+
elseif (info==XLOG_HEAP_INPLACE)
3592+
{
3593+
xl_heap_inplace*xlrec= (xl_heap_inplace*)rec;
3594+
3595+
appendStringInfo(buf,"inplace: ");
3596+
out_target(buf,&(xlrec->target));
3597+
}
34453598
else
34463599
appendStringInfo(buf,"UNKNOWN");
34473600
}

‎src/backend/access/nbtree/nbtree.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,18 @@
1212
* Portions Copyright (c) 1994, Regents of the University of California
1313
*
1414
* IDENTIFICATION
15-
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.148 2006/05/08 00:00:10 tgl Exp $
15+
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.149 2006/05/10 23:18:39 tgl Exp $
1616
*
1717
*-------------------------------------------------------------------------
1818
*/
1919
#include"postgres.h"
2020

2121
#include"access/genam.h"
22-
#include"access/heapam.h"
2322
#include"access/nbtree.h"
2423
#include"catalog/index.h"
2524
#include"commands/vacuum.h"
26-
#include"miscadmin.h"
2725
#include"storage/freespace.h"
28-
#include"storage/smgr.h"
29-
#include"utils/inval.h"
26+
#include"storage/lmgr.h"
3027
#include"utils/memutils.h"
3128

3229

@@ -84,6 +81,7 @@ btbuild(PG_FUNCTION_ARGS)
8481
Relationheap= (Relation)PG_GETARG_POINTER(0);
8582
Relationindex= (Relation)PG_GETARG_POINTER(1);
8683
IndexInfo*indexInfo= (IndexInfo*)PG_GETARG_POINTER(2);
84+
IndexBuildResult*result;
8785
doublereltuples;
8886
BTBuildStatebuildstate;
8987

@@ -149,18 +147,20 @@ btbuild(PG_FUNCTION_ARGS)
149147
/*
150148
* If we are reindexing a pre-existing index, it is critical to send out
151149
* a relcache invalidation SI message to ensure all backends re-read the
152-
* index metapage. In most circumstances the update-stats operation will
153-
* cause that to happen, but at the moment there are corner cases where
154-
* no pg_class update will occur, so force an inval here. XXX FIXME:
155-
* the upper levels of CREATE INDEX should handle the stats update as
156-
* well as guaranteeing relcache inval.
150+
* index metapage. We expect that the caller will ensure that happens
151+
* (typically as a side effect of updating index stats, but it must
152+
* happen even if the stats don't change!)
157153
*/
158-
CacheInvalidateRelcache(index);
159154

160-
/* since we just counted the # of tuples, may as well update stats */
161-
IndexCloseAndUpdateStats(heap,reltuples,index,buildstate.indtuples);
155+
/*
156+
* Return statistics
157+
*/
158+
result= (IndexBuildResult*)palloc(sizeof(IndexBuildResult));
162159

163-
PG_RETURN_VOID();
160+
result->heap_tuples=reltuples;
161+
result->index_tuples=buildstate.indtuples;
162+
163+
PG_RETURN_POINTER(result);
164164
}
165165

166166
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp