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

Commit6707dd4

Browse files
committed
Back-patch recent fixes for gistchoose and gistRelocateBuildBuffersOnSplit.
This back-ports commitsc8ba697 ande5db11c, which fix one definite and onespeculative bug in gistchoose, and make the code a lot more intelligible aswell. In 9.2 only, this also affects the largely-copied-and-pasted logicin gistRelocateBuildBuffersOnSplit.The impact of the bugs was that the functions might make poor decisionsas to which index tree branch to push a new entry down into, resulting inGiST index bloat and poor performance. The fixes rectify these decisionsfor future insertions, but a REINDEX would be needed to clean up anyexisting index bloat.Alexander Korotkov, Robert Haas, Tom Lane
1 parentf6956eb commit6707dd4

File tree

1 file changed

+73
-25
lines changed

1 file changed

+73
-25
lines changed

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

Lines changed: 73 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -365,72 +365,120 @@ gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *gis
365365
}
366366

367367
/*
368-
* find entry with lowest penalty
368+
* Search an upper index page for the entry with lowest penalty for insertion
369+
* of the new index key contained in "it".
370+
*
371+
* Returns the index of the page entry to insert into.
369372
*/
370373
OffsetNumber
371374
gistchoose(Relationr,Pagep,IndexTupleit,/* it has compressed entry */
372375
GISTSTATE*giststate)
373376
{
377+
OffsetNumberresult;
374378
OffsetNumbermaxoff;
375379
OffsetNumberi;
376-
OffsetNumberwhich;
377-
floatsum_grow,
378-
which_grow[INDEX_MAX_KEYS];
380+
floatbest_penalty[INDEX_MAX_KEYS];
379381
GISTENTRYentry,
380382
identry[INDEX_MAX_KEYS];
381383
boolisnull[INDEX_MAX_KEYS];
382384

383-
maxoff=PageGetMaxOffsetNumber(p);
384-
*which_grow=-1.0;
385-
which=InvalidOffsetNumber;
386-
sum_grow=1;
385+
Assert(!GistPageIsLeaf(p));
386+
387387
gistDeCompressAtt(giststate,r,
388388
it,NULL, (OffsetNumber)0,
389389
identry,isnull);
390390

391+
/* we'll return FirstOffsetNumber if page is empty (shouldn't happen) */
392+
result=FirstOffsetNumber;
393+
394+
/*
395+
* The index may have multiple columns, and there's a penalty value for
396+
* each column. The penalty associated with a column that appears earlier
397+
* in the index definition is strictly more important than the penalty of
398+
* a column that appears later in the index definition.
399+
*
400+
* best_penalty[j] is the best penalty we have seen so far for column j,
401+
* or -1 when we haven't yet examined column j. Array entries to the
402+
* right of the first -1 are undefined.
403+
*/
404+
best_penalty[0]=-1;
405+
406+
/*
407+
* Loop over tuples on page.
408+
*/
409+
maxoff=PageGetMaxOffsetNumber(p);
391410
Assert(maxoff >=FirstOffsetNumber);
392-
Assert(!GistPageIsLeaf(p));
393411

394-
for (i=FirstOffsetNumber;i <=maxoff&&sum_grow;i=OffsetNumberNext(i))
412+
for (i=FirstOffsetNumber;i <=maxoff;i=OffsetNumberNext(i))
395413
{
396-
intj;
397414
IndexTupleitup= (IndexTuple)PageGetItem(p,PageGetItemId(p,i));
415+
boolzero_penalty;
416+
intj;
398417

399-
sum_grow=0;
418+
zero_penalty= true;
419+
420+
/* Loop over index attributes. */
400421
for (j=0;j<r->rd_att->natts;j++)
401422
{
402423
Datumdatum;
403424
floatusize;
404425
boolIsNull;
405426

427+
/* Compute penalty for this column. */
406428
datum=index_getattr(itup,j+1,giststate->tupdesc,&IsNull);
407429
gistdentryinit(giststate,j,&entry,datum,r,p,i,
408430
FALSE,IsNull);
409431
usize=gistpenalty(giststate,j,&entry,IsNull,
410432
&identry[j],isnull[j]);
433+
if (usize>0)
434+
zero_penalty= false;
411435

412-
if (which_grow[j]<0||usize<which_grow[j])
436+
if (best_penalty[j]<0||usize<best_penalty[j])
437+
{
438+
/*
439+
* New best penalty for column. Tentatively select this tuple
440+
* as the target, and record the best penalty.Then reset the
441+
* next column's penalty to "unknown" (and indirectly, the
442+
* same for all the ones to its right). This will force us to
443+
* adopt this tuple's penalty values as the best for all the
444+
* remaining columns during subsequent loop iterations.
445+
*/
446+
result=i;
447+
best_penalty[j]=usize;
448+
449+
if (j<r->rd_att->natts-1)
450+
best_penalty[j+1]=-1;
451+
}
452+
elseif (best_penalty[j]==usize)
413453
{
414-
which=i;
415-
which_grow[j]=usize;
416-
if (j<r->rd_att->natts-1&&i==FirstOffsetNumber)
417-
which_grow[j+1]=-1;
418-
sum_grow+=which_grow[j];
454+
/*
455+
* The current tuple is exactly as good for this column as the
456+
* best tuple seen so far.The next iteration of this loop
457+
* will compare the next column.
458+
*/
419459
}
420-
elseif (which_grow[j]==usize)
421-
sum_grow+=usize;
422460
else
423461
{
424-
sum_grow=1;
462+
/*
463+
* The current tuple is worse for this column than the best
464+
* tuple seen so far. Skip the remaining columns and move on
465+
* to the next tuple, if any.
466+
*/
467+
zero_penalty= false;/* so outer loop won't exit */
425468
break;
426469
}
427470
}
428-
}
429471

430-
if (which==InvalidOffsetNumber)
431-
which=FirstOffsetNumber;
472+
/*
473+
* If we find a tuple with zero penalty for all columns, there's no
474+
* need to examine remaining tuples; just break out of the loop and
475+
* return it.
476+
*/
477+
if (zero_penalty)
478+
break;
479+
}
432480

433-
returnwhich;
481+
returnresult;
434482
}
435483

436484
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp