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

Commit86d911e

Browse files
committed
Allow index AMs to cache data across aminsert calls within a SQL command.
It's always been possible for index AMs to cache data across successiveamgettuple calls within a single SQL command: the IndexScanDesc.opaquefield is meant for precisely that. However, no comparable facilityexists for amortizing setup work across successive aminsert calls.This patch adds such a feature and teaches GIN, GIST, and BRIN to use itto amortize catalog lookups they'd previously been doing on every call.(The other standard index AMs keep everything they need in the relcache,so there's little to improve there.)For GIN, the overall improvement in a statement that inserts many rowscan be as much as 10%, though it seems a bit less for the other two.In addition, this makes a really significant difference in runtimefor CLOBBER_CACHE_ALWAYS tests, since in those builds the repeatedcatalog lookups are vastly more expensive.The reason this has been hard up to now is that the aminsert function isnot passed any useful place to cache per-statement data. What I chose todo is to add suitable fields to struct IndexInfo and pass that to aminsert.That's not widening the index AM API very much because IndexInfo is alreadywithin the ken of ambuild; in fact, by passing the same info to aminsertas to ambuild, this is really removing an inconsistency in the AM API.Discussion:https://postgr.es/m/27568.1486508680@sss.pgh.pa.us
1 parent7c5d8c1 commit86d911e

File tree

26 files changed

+117
-52
lines changed

26 files changed

+117
-52
lines changed

‎contrib/bloom/blinsert.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,9 @@ blbuildempty(Relation index)
190190
*/
191191
bool
192192
blinsert(Relationindex,Datum*values,bool*isnull,
193-
ItemPointerht_ctid,RelationheapRel,IndexUniqueCheckcheckUnique)
193+
ItemPointerht_ctid,RelationheapRel,
194+
IndexUniqueCheckcheckUnique,
195+
IndexInfo*indexInfo)
194196
{
195197
BloomStateblstate;
196198
BloomTuple*itup;

‎contrib/bloom/bloom.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,8 @@ extern bool blvalidate(Oid opclassoid);
189189
/* index access method interface functions */
190190
externboolblinsert(Relationindex,Datum*values,bool*isnull,
191191
ItemPointerht_ctid,RelationheapRel,
192-
IndexUniqueCheckcheckUnique);
192+
IndexUniqueCheckcheckUnique,
193+
structIndexInfo*indexInfo);
193194
externIndexScanDescblbeginscan(Relationr,intnkeys,intnorderbys);
194195
externint64blgetbitmap(IndexScanDescscan,TIDBitmap*tbm);
195196
externvoidblrescan(IndexScanDescscan,ScanKeyscankey,intnscankeys,

‎doc/src/sgml/indexam.sgml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,8 @@ aminsert (Relation indexRelation,
259259
bool *isnull,
260260
ItemPointer heap_tid,
261261
Relation heapRelation,
262-
IndexUniqueCheck checkUnique);
262+
IndexUniqueCheck checkUnique,
263+
IndexInfo *indexInfo);
263264
</programlisting>
264265
Insert a new tuple into an existing index. The <literal>values</> and
265266
<literal>isnull</> arrays give the key values to be indexed, and
@@ -287,6 +288,14 @@ aminsert (Relation indexRelation,
287288
indexed, <function>aminsert</> should just return without doing anything.
288289
</para>
289290

291+
<para>
292+
If the index AM wishes to cache data across successive index insertions
293+
within a SQL statement, it can allocate space
294+
in <literal>indexInfo-&gt;ii_Context</literal> and store a pointer to the
295+
data in <literal>indexInfo-&gt;ii_AmCache</literal> (which will be NULL
296+
initially).
297+
</para>
298+
290299
<para>
291300
<programlisting>
292301
IndexBulkDeleteResult *

‎src/backend/access/brin/brin.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -131,14 +131,15 @@ brinhandler(PG_FUNCTION_ARGS)
131131
bool
132132
brininsert(RelationidxRel,Datum*values,bool*nulls,
133133
ItemPointerheaptid,RelationheapRel,
134-
IndexUniqueCheckcheckUnique)
134+
IndexUniqueCheckcheckUnique,
135+
IndexInfo*indexInfo)
135136
{
136137
BlockNumberpagesPerRange;
137-
BrinDesc*bdesc=NULL;
138+
BrinDesc*bdesc=(BrinDesc*)indexInfo->ii_AmCache;
138139
BrinRevmap*revmap;
139140
Bufferbuf=InvalidBuffer;
140141
MemoryContexttupcxt=NULL;
141-
MemoryContextoldcxt=NULL;
142+
MemoryContextoldcxt=CurrentMemoryContext;
142143

143144
revmap=brinRevmapInitialize(idxRel,&pagesPerRange,NULL);
144145

@@ -163,14 +164,21 @@ brininsert(Relation idxRel, Datum *values, bool *nulls,
163164
if (!brtup)
164165
break;
165166

166-
/* First time through? */
167+
/* First time through in this statement? */
167168
if (bdesc==NULL)
168169
{
170+
MemoryContextSwitchTo(indexInfo->ii_Context);
169171
bdesc=brin_build_desc(idxRel);
172+
indexInfo->ii_AmCache= (void*)bdesc;
173+
MemoryContextSwitchTo(oldcxt);
174+
}
175+
/* First time through in this brininsert call? */
176+
if (tupcxt==NULL)
177+
{
170178
tupcxt=AllocSetContextCreate(CurrentMemoryContext,
171179
"brininsert cxt",
172180
ALLOCSET_DEFAULT_SIZES);
173-
oldcxt=MemoryContextSwitchTo(tupcxt);
181+
MemoryContextSwitchTo(tupcxt);
174182
}
175183

176184
dtup=brin_deform_tuple(bdesc,brtup);
@@ -261,12 +269,9 @@ brininsert(Relation idxRel, Datum *values, bool *nulls,
261269
brinRevmapTerminate(revmap);
262270
if (BufferIsValid(buf))
263271
ReleaseBuffer(buf);
264-
if (bdesc!=NULL)
265-
{
266-
brin_free_desc(bdesc);
267-
MemoryContextSwitchTo(oldcxt);
272+
MemoryContextSwitchTo(oldcxt);
273+
if (tupcxt!=NULL)
268274
MemoryContextDelete(tupcxt);
269-
}
270275

271276
return false;
272277
}

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

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -482,39 +482,48 @@ ginHeapTupleInsert(GinState *ginstate, OffsetNumber attnum,
482482
bool
483483
gininsert(Relationindex,Datum*values,bool*isnull,
484484
ItemPointerht_ctid,RelationheapRel,
485-
IndexUniqueCheckcheckUnique)
485+
IndexUniqueCheckcheckUnique,
486+
IndexInfo*indexInfo)
486487
{
487-
GinStateginstate;
488+
GinState*ginstate= (GinState*)indexInfo->ii_AmCache;
488489
MemoryContextoldCtx;
489490
MemoryContextinsertCtx;
490491
inti;
491492

493+
/* Initialize GinState cache if first call in this statement */
494+
if (ginstate==NULL)
495+
{
496+
oldCtx=MemoryContextSwitchTo(indexInfo->ii_Context);
497+
ginstate= (GinState*)palloc(sizeof(GinState));
498+
initGinState(ginstate,index);
499+
indexInfo->ii_AmCache= (void*)ginstate;
500+
MemoryContextSwitchTo(oldCtx);
501+
}
502+
492503
insertCtx=AllocSetContextCreate(CurrentMemoryContext,
493504
"Gin insert temporary context",
494505
ALLOCSET_DEFAULT_SIZES);
495506

496507
oldCtx=MemoryContextSwitchTo(insertCtx);
497508

498-
initGinState(&ginstate,index);
499-
500509
if (GinGetUseFastUpdate(index))
501510
{
502511
GinTupleCollectorcollector;
503512

504513
memset(&collector,0,sizeof(GinTupleCollector));
505514

506-
for (i=0;i<ginstate.origTupdesc->natts;i++)
507-
ginHeapTupleFastCollect(&ginstate,&collector,
515+
for (i=0;i<ginstate->origTupdesc->natts;i++)
516+
ginHeapTupleFastCollect(ginstate,&collector,
508517
(OffsetNumber) (i+1),
509518
values[i],isnull[i],
510519
ht_ctid);
511520

512-
ginHeapTupleFastInsert(&ginstate,&collector);
521+
ginHeapTupleFastInsert(ginstate,&collector);
513522
}
514523
else
515524
{
516-
for (i=0;i<ginstate.origTupdesc->natts;i++)
517-
ginHeapTupleInsert(&ginstate, (OffsetNumber) (i+1),
525+
for (i=0;i<ginstate->origTupdesc->natts;i++)
526+
ginHeapTupleInsert(ginstate, (OffsetNumber) (i+1),
518527
values[i],isnull[i],
519528
ht_ctid);
520529
}

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

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include"access/gistscan.h"
1919
#include"catalog/pg_collation.h"
2020
#include"miscadmin.h"
21+
#include"nodes/execnodes.h"
2122
#include"utils/builtins.h"
2223
#include"utils/index_selfuncs.h"
2324
#include"utils/memutils.h"
@@ -144,21 +145,23 @@ gistbuildempty(Relation index)
144145
bool
145146
gistinsert(Relationr,Datum*values,bool*isnull,
146147
ItemPointerht_ctid,RelationheapRel,
147-
IndexUniqueCheckcheckUnique)
148+
IndexUniqueCheckcheckUnique,
149+
IndexInfo*indexInfo)
148150
{
151+
GISTSTATE*giststate= (GISTSTATE*)indexInfo->ii_AmCache;
149152
IndexTupleitup;
150-
GISTSTATE*giststate;
151153
MemoryContextoldCxt;
152154

153-
giststate=initGISTstate(r);
155+
/* Initialize GISTSTATE cache if first call in this statement */
156+
if (giststate==NULL)
157+
{
158+
oldCxt=MemoryContextSwitchTo(indexInfo->ii_Context);
159+
giststate=initGISTstate(r);
160+
giststate->tempCxt=createTempGistContext();
161+
indexInfo->ii_AmCache= (void*)giststate;
162+
MemoryContextSwitchTo(oldCxt);
163+
}
154164

155-
/*
156-
* We use the giststate's scan context as temp context too. This means
157-
* that any memory leaked by the support functions is not reclaimed until
158-
* end of insert. In most cases, we aren't going to call the support
159-
* functions very many times before finishing the insert, so this seems
160-
* cheaper than resetting a temp context for each function call.
161-
*/
162165
oldCxt=MemoryContextSwitchTo(giststate->tempCxt);
163166

164167
itup=gistFormTuple(giststate,r,
@@ -169,7 +172,7 @@ gistinsert(Relation r, Datum *values, bool *isnull,
169172

170173
/* cleanup */
171174
MemoryContextSwitchTo(oldCxt);
172-
freeGISTstate(giststate);
175+
MemoryContextReset(giststate->tempCxt);
173176

174177
return false;
175178
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,8 @@ hashbuildCallback(Relation index,
232232
bool
233233
hashinsert(Relationrel,Datum*values,bool*isnull,
234234
ItemPointerht_ctid,RelationheapRel,
235-
IndexUniqueCheckcheckUnique)
235+
IndexUniqueCheckcheckUnique,
236+
IndexInfo*indexInfo)
236237
{
237238
Datumindex_values[1];
238239
boolindex_isnull[1];

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,7 +1604,9 @@ toast_save_datum(Relation rel, Datum value,
16041604
* Create the index entry. We cheat a little here by not using
16051605
* FormIndexDatum: this relies on the knowledge that the index columns
16061606
* are the same as the initial columns of the table for all the
1607-
* indexes.
1607+
* indexes. We also cheat by not providing an IndexInfo: this is okay
1608+
* for now because btree doesn't need one, but we might have to be
1609+
* more honest someday.
16081610
*
16091611
* Note also that there had better not be any user-created index on
16101612
* the TOAST table, since we don't bother to update anything else.
@@ -1617,7 +1619,8 @@ toast_save_datum(Relation rel, Datum value,
16171619
&(toasttup->t_self),
16181620
toastrel,
16191621
toastidxs[i]->rd_index->indisunique ?
1620-
UNIQUE_CHECK_YES :UNIQUE_CHECK_NO);
1622+
UNIQUE_CHECK_YES :UNIQUE_CHECK_NO,
1623+
NULL);
16211624
}
16221625

16231626
/*

‎src/backend/access/index/indexam.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,8 @@ index_insert(Relation indexRelation,
196196
bool*isnull,
197197
ItemPointerheap_t_ctid,
198198
RelationheapRelation,
199-
IndexUniqueCheckcheckUnique)
199+
IndexUniqueCheckcheckUnique,
200+
IndexInfo*indexInfo)
200201
{
201202
RELATION_CHECKS;
202203
CHECK_REL_PROCEDURE(aminsert);
@@ -208,7 +209,7 @@ index_insert(Relation indexRelation,
208209

209210
returnindexRelation->rd_amroutine->aminsert(indexRelation,values,isnull,
210211
heap_t_ctid,heapRelation,
211-
checkUnique);
212+
checkUnique,indexInfo);
212213
}
213214

214215
/*

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,8 @@ btbuildempty(Relation index)
276276
bool
277277
btinsert(Relationrel,Datum*values,bool*isnull,
278278
ItemPointerht_ctid,RelationheapRel,
279-
IndexUniqueCheckcheckUnique)
279+
IndexUniqueCheckcheckUnique,
280+
IndexInfo*indexInfo)
280281
{
281282
boolresult;
282283
IndexTupleitup;

‎src/backend/access/spgist/spginsert.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,8 @@ spgbuildempty(Relation index)
206206
bool
207207
spginsert(Relationindex,Datum*values,bool*isnull,
208208
ItemPointerht_ctid,RelationheapRel,
209-
IndexUniqueCheckcheckUnique)
209+
IndexUniqueCheckcheckUnique,
210+
IndexInfo*indexInfo)
210211
{
211212
SpGistStatespgstate;
212213
MemoryContextoldCtx;

‎src/backend/catalog/index.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1687,6 +1687,10 @@ BuildIndexInfo(Relation index)
16871687
ii->ii_Concurrent= false;
16881688
ii->ii_BrokenHotChain= false;
16891689

1690+
/* set up for possible use by index AM */
1691+
ii->ii_AmCache=NULL;
1692+
ii->ii_Context=CurrentMemoryContext;
1693+
16901694
returnii;
16911695
}
16921696

@@ -3158,7 +3162,8 @@ validate_index_heapscan(Relation heapRelation,
31583162
&rootTuple,
31593163
heapRelation,
31603164
indexInfo->ii_Unique ?
3161-
UNIQUE_CHECK_YES :UNIQUE_CHECK_NO);
3165+
UNIQUE_CHECK_YES :UNIQUE_CHECK_NO,
3166+
indexInfo);
31623167

31633168
state->tups_inserted+=1;
31643169
}

‎src/backend/catalog/indexing.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple)
139139
&(heapTuple->t_self),/* tid of heap tuple */
140140
heapRelation,
141141
relationDescs[i]->rd_index->indisunique ?
142-
UNIQUE_CHECK_YES :UNIQUE_CHECK_NO);
142+
UNIQUE_CHECK_YES :UNIQUE_CHECK_NO,
143+
indexInfo);
143144
}
144145

145146
ExecDropSingleTupleTableSlot(slot);

‎src/backend/catalog/toasting.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,8 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
315315
indexInfo->ii_ReadyForInserts= true;
316316
indexInfo->ii_Concurrent= false;
317317
indexInfo->ii_BrokenHotChain= false;
318+
indexInfo->ii_AmCache=NULL;
319+
indexInfo->ii_Context=CurrentMemoryContext;
318320

319321
collationObjectId[0]=InvalidOid;
320322
collationObjectId[1]=InvalidOid;

‎src/backend/commands/constraint.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ unique_key_recheck(PG_FUNCTION_ARGS)
165165
* index will know about.
166166
*/
167167
index_insert(indexRel,values,isnull,&(new_row->t_self),
168-
trigdata->tg_relation,UNIQUE_CHECK_EXISTING);
168+
trigdata->tg_relation,UNIQUE_CHECK_EXISTING,
169+
indexInfo);
169170
}
170171
else
171172
{

‎src/backend/commands/indexcmds.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ CheckIndexCompatible(Oid oldId,
183183
indexInfo->ii_ExclusionOps=NULL;
184184
indexInfo->ii_ExclusionProcs=NULL;
185185
indexInfo->ii_ExclusionStrats=NULL;
186+
indexInfo->ii_AmCache=NULL;
187+
indexInfo->ii_Context=CurrentMemoryContext;
186188
typeObjectId= (Oid*)palloc(numberOfAttributes*sizeof(Oid));
187189
collationObjectId= (Oid*)palloc(numberOfAttributes*sizeof(Oid));
188190
classObjectId= (Oid*)palloc(numberOfAttributes*sizeof(Oid));
@@ -562,6 +564,8 @@ DefineIndex(Oid relationId,
562564
indexInfo->ii_ReadyForInserts= !stmt->concurrent;
563565
indexInfo->ii_Concurrent=stmt->concurrent;
564566
indexInfo->ii_BrokenHotChain= false;
567+
indexInfo->ii_AmCache=NULL;
568+
indexInfo->ii_Context=CurrentMemoryContext;
565569

566570
typeObjectId= (Oid*)palloc(numberOfAttributes*sizeof(Oid));
567571
collationObjectId= (Oid*)palloc(numberOfAttributes*sizeof(Oid));

‎src/backend/executor/execIndexing.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,8 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
391391
isnull,/* null flags */
392392
tupleid,/* tid of heap tuple */
393393
heapRelation,/* heap relation */
394-
checkUnique);/* type of uniqueness check to do */
394+
checkUnique,/* type of uniqueness check to do */
395+
indexInfo);/* index AM may need this */
395396

396397
/*
397398
* If the index has an associated exclusion constraint, check that.

‎src/include/access/amapi.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ typedef bool (*aminsert_function) (Relation indexRelation,
7272
bool*isnull,
7373
ItemPointerheap_tid,
7474
RelationheapRelation,
75-
IndexUniqueCheckcheckUnique);
75+
IndexUniqueCheckcheckUnique,
76+
structIndexInfo*indexInfo);
7677

7778
/* bulk delete */
7879
typedefIndexBulkDeleteResult*(*ambulkdelete_function) (IndexVacuumInfo*info,

‎src/include/access/brin_internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ extern IndexBuildResult *brinbuild(Relation heap, Relation index,
8989
externvoidbrinbuildempty(Relationindex);
9090
externboolbrininsert(RelationidxRel,Datum*values,bool*nulls,
9191
ItemPointerheaptid,RelationheapRel,
92-
IndexUniqueCheckcheckUnique);
92+
IndexUniqueCheckcheckUnique,
93+
structIndexInfo*indexInfo);
9394
externIndexScanDescbrinbeginscan(Relationr,intnkeys,intnorderbys);
9495
externint64bringetbitmap(IndexScanDescscan,TIDBitmap*tbm);
9596
externvoidbrinrescan(IndexScanDescscan,ScanKeyscankey,intnscankeys,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp