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

Commitfb0919f

Browse files
committed
Don't assume that max offset number stays fixed on a page when we're
not holding a pin on the page. Use double instead of long to countrows in relation, so that code still works for > LONG_MAX rows in rel.
1 parent6497a7f commitfb0919f

File tree

1 file changed

+67
-66
lines changed

1 file changed

+67
-66
lines changed

‎src/backend/commands/analyze.c

Lines changed: 67 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.21 2001/06/22 19:16:21 wieck Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.22 2001/07/05 19:33:35 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -97,8 +97,8 @@ typedef struct
9797
}ScalarMCVItem;
9898

9999

100-
#defineswapInt(a,b){int _tmp; _tmp=a; a=b; b=_tmp;}
101-
#defineswapDatum(a,b){Datum _tmp; _tmp=a; a=b; b=_tmp;}
100+
#defineswapInt(a,b)do{int _tmp; _tmp=a; a=b; b=_tmp;} while(0)
101+
#defineswapDatum(a,b)do{Datum _tmp; _tmp=a; a=b; b=_tmp;} while(0)
102102

103103

104104
staticintMESSAGE_LEVEL;
@@ -111,20 +111,18 @@ static int *datumCmpTupnoLink;
111111

112112
staticVacAttrStats*examine_attribute(Relationonerel,intattnum);
113113
staticintacquire_sample_rows(Relationonerel,HeapTuple*rows,
114-
inttargrows,long*totalrows);
114+
inttargrows,double*totalrows);
115115
staticdoublerandom_fract(void);
116116
staticdoubleinit_selection_state(intn);
117-
staticlongselect_next_random_record(longt,intn,double*stateptr);
117+
staticdoubleselect_next_random_record(doublet,intn,double*stateptr);
118118
staticintcompare_rows(constvoid*a,constvoid*b);
119119
staticintcompare_scalars(constvoid*a,constvoid*b);
120120
staticintcompare_mcvs(constvoid*a,constvoid*b);
121-
staticOffsetNumberget_page_max_offset(Relationrelation,
122-
BlockNumberblocknumber);
123121
staticvoidcompute_minimal_stats(VacAttrStats*stats,
124-
TupleDesctupDesc,longtotalrows,
122+
TupleDesctupDesc,doubletotalrows,
125123
HeapTuple*rows,intnumrows);
126124
staticvoidcompute_scalar_stats(VacAttrStats*stats,
127-
TupleDesctupDesc,longtotalrows,
125+
TupleDesctupDesc,doubletotalrows,
128126
HeapTuple*rows,intnumrows);
129127
staticvoidupdate_attstats(Oidrelid,intnatts,VacAttrStats**vacattrstats);
130128

@@ -143,7 +141,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
143141
VacAttrStats**vacattrstats;
144142
inttargrows,
145143
numrows;
146-
longtotalrows;
144+
doubletotalrows;
147145
HeapTuple*rows;
148146
HeapTupletuple;
149147

@@ -298,7 +296,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
298296
if (!vacstmt->vacuum)
299297
vac_update_relstats(RelationGetRelid(onerel),
300298
onerel->rd_nblocks,
301-
(double)totalrows,
299+
totalrows,
302300
RelationGetForm(onerel)->relhasindex);
303301

304302
/*
@@ -488,7 +486,7 @@ examine_attribute(Relation onerel, int attnum)
488486
*/
489487
staticint
490488
acquire_sample_rows(Relationonerel,HeapTuple*rows,inttargrows,
491-
long*totalrows)
489+
double*totalrows)
492490
{
493491
intnumrows=0;
494492
HeapScanDescscan;
@@ -499,7 +497,7 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
499497
OffsetNumberlastoffset;
500498
intnumest;
501499
doubletuplesperpage;
502-
longt;
500+
doublet;
503501
doublerstate;
504502

505503
Assert(targrows>1);
@@ -520,7 +518,7 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
520518
*/
521519
if (!HeapTupleIsValid(tuple))
522520
{
523-
*totalrows=numrows;
521+
*totalrows=(double)numrows;
524522
returnnumrows;
525523
}
526524
/*
@@ -565,20 +563,22 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
565563
}
566564
tuplesperpage= (double)numest / (double)estblock;
567565

568-
t=numrows;/* t is the # of records processed so far */
566+
t=(double)numrows;/* t is the # of records processed so far */
569567
rstate=init_selection_state(targrows);
570568
for (;;)
571569
{
572570
doubletargpos;
573571
BlockNumbertargblock;
572+
Buffertargbuffer;
573+
Pagetargpage;
574574
OffsetNumbertargoffset,
575575
maxoffset;
576576

577577
t=select_next_random_record(t,targrows,&rstate);
578578
/* Try to read the t'th record in the table */
579-
targpos=(double)t /tuplesperpage;
579+
targpos=t /tuplesperpage;
580580
targblock= (BlockNumber)targpos;
581-
targoffset= ((int) (targpos-targblock)*tuplesperpage)+
581+
targoffset= ((int) ((targpos-targblock)*tuplesperpage))+
582582
FirstOffsetNumber;
583583
/* Make sure we are past the last selected record */
584584
if (targblock <=lastblock)
@@ -595,21 +595,37 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
595595
*/
596596
if (targblock >=onerel->rd_nblocks)
597597
break;
598-
maxoffset=get_page_max_offset(onerel,targblock);
598+
/*
599+
* We must maintain a pin on the target page's buffer to ensure that
600+
* the maxoffset value stays good (else concurrent VACUUM might
601+
* delete tuples out from under us). Hence, pin the page until we
602+
* are done looking at it. We don't maintain a lock on the page,
603+
* so tuples could get added to it, but we ignore such tuples.
604+
*/
605+
targbuffer=ReadBuffer(onerel,targblock);
606+
if (!BufferIsValid(targbuffer))
607+
elog(ERROR,"acquire_sample_rows: ReadBuffer(%s,%u) failed",
608+
RelationGetRelationName(onerel),targblock);
609+
LockBuffer(targbuffer,BUFFER_LOCK_SHARE);
610+
targpage=BufferGetPage(targbuffer);
611+
maxoffset=PageGetMaxOffsetNumber(targpage);
612+
LockBuffer(targbuffer,BUFFER_LOCK_UNLOCK);
613+
599614
for (;;)
600615
{
601616
HeapTupleDatatargtuple;
602-
Buffertargbuffer;
617+
Buffertupbuffer;
603618

604619
if (targoffset>maxoffset)
605620
{
606621
/* Fell off end of this page, try next */
622+
ReleaseBuffer(targbuffer);
607623
targblock++;
608624
targoffset=FirstOffsetNumber;
609625
gotopageloop;
610626
}
611627
ItemPointerSet(&targtuple.t_self,targblock,targoffset);
612-
heap_fetch(onerel,SnapshotNow,&targtuple,&targbuffer,NULL);
628+
heap_fetch(onerel,SnapshotNow,&targtuple,&tupbuffer,NULL);
613629
if (targtuple.t_data!=NULL)
614630
{
615631
/*
@@ -621,6 +637,9 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
621637
Assert(k >=0&&k<targrows);
622638
heap_freetuple(rows[k]);
623639
rows[k]=heap_copytuple(&targtuple);
640+
/* this releases the second pin acquired by heap_fetch: */
641+
ReleaseBuffer(tupbuffer);
642+
/* this releases the initial pin: */
624643
ReleaseBuffer(targbuffer);
625644
lastblock=targblock;
626645
lastoffset=targoffset;
@@ -639,7 +658,7 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
639658
/*
640659
* Estimate total number of valid rows in relation.
641660
*/
642-
*totalrows=(long) (onerel->rd_nblocks*tuplesperpage+0.5);
661+
*totalrows=floor((double)onerel->rd_nblocks*tuplesperpage+0.5);
643662

644663
returnnumrows;
645664
}
@@ -667,6 +686,12 @@ random_fract(void)
667686
* of the last record processed and next record to process. The only extra
668687
* state needed between calls is W, a random state variable.
669688
*
689+
* Note: the original algorithm defines t, S, numer, and denom as integers.
690+
* Here we express them as doubles to avoid overflow if the number of rows
691+
* in the table exceeds INT_MAX. The algorithm should work as long as the
692+
* row count does not become so large that it is not represented accurately
693+
* in a double (on IEEE-math machines this would be around 2^52 rows).
694+
*
670695
* init_selection_state computes the initial W value.
671696
*
672697
* Given that we've already processed t records (t >= n),
@@ -680,36 +705,36 @@ init_selection_state(int n)
680705
returnexp(-log(random_fract())/n);
681706
}
682707

683-
staticlong
684-
select_next_random_record(longt,intn,double*stateptr)
708+
staticdouble
709+
select_next_random_record(doublet,intn,double*stateptr)
685710
{
686711
/* The magic constant here is T from Vitter's paper */
687-
if (t <= (22*n))
712+
if (t <= (22.0*n))
688713
{
689714
/* Process records using Algorithm X until t is large enough */
690715
doubleV,
691716
quot;
692717

693718
V=random_fract();/* Generate V */
694-
t++;
695-
quot= (double) (t-n) / (double)t;
719+
t+=1;
720+
quot= (t-(double)n) /t;
696721
/* Find min S satisfying (4.1) */
697722
while (quot>V)
698723
{
699-
t++;
700-
quot *= (double) (t-n) / (double)t;
724+
t+=1;
725+
quot *= (t-(double)n) /t;
701726
}
702727
}
703728
else
704729
{
705730
/* Now apply Algorithm Z */
706731
doubleW=*stateptr;
707-
longterm=t-n+1;
708-
intS;
732+
doubleterm=t- (double)n+1;
733+
doubleS;
709734

710735
for (;;)
711736
{
712-
longnumer,
737+
doublenumer,
713738
numer_lim,
714739
denom;
715740
doubleU,
@@ -722,9 +747,9 @@ select_next_random_record(long t, int n, double *stateptr)
722747
/* Generate U and X */
723748
U=random_fract();
724749
X=t* (W-1.0);
725-
S=X;/* S is tentatively set to floor(X) */
750+
S=floor(X);/* S is tentatively set to floor(X) */
726751
/* Test if U <= h(S)/cg(X) in the manner of (6.3) */
727-
tmp= (double) (t+1) / (double)term;
752+
tmp= (t+1) /term;
728753
lhs=exp(log(((U*tmp*tmp)* (term+S))/(t+X))/n);
729754
rhs= (((t+X)/(term+S))*term)/t;
730755
if (lhs <=rhs)
@@ -734,20 +759,20 @@ select_next_random_record(long t, int n, double *stateptr)
734759
}
735760
/* Test if U <= f(S)/cg(X) */
736761
y= (((U* (t+1))/term)* (t+S+1))/(t+X);
737-
if (n<S)
762+
if ((double)n<S)
738763
{
739764
denom=t;
740765
numer_lim=term+S;
741766
}
742767
else
743768
{
744-
denom=t-n+S;
769+
denom=t-(double)n+S;
745770
numer_lim=t+1;
746771
}
747-
for (numer=t+S;numer >=numer_lim;numer--)
772+
for (numer=t+S;numer >=numer_lim;numer-=1)
748773
{
749-
y *=(double)numer / (double)denom;
750-
denom--;
774+
y *=numer /denom;
775+
denom-=1;
751776
}
752777
W=exp(-log(random_fract())/n);/* Generate W in advance */
753778
if (exp(log(y)/n) <= (t+X)/t)
@@ -783,30 +808,6 @@ compare_rows(const void *a, const void *b)
783808
return0;
784809
}
785810

786-
/*
787-
* Discover the largest valid tuple offset number on the given page
788-
*
789-
* This code probably ought to live in some other module.
790-
*/
791-
staticOffsetNumber
792-
get_page_max_offset(Relationrelation,BlockNumberblocknumber)
793-
{
794-
Bufferbuffer;
795-
Pagep;
796-
OffsetNumberoffnum;
797-
798-
buffer=ReadBuffer(relation,blocknumber);
799-
if (!BufferIsValid(buffer))
800-
elog(ERROR,"get_page_max_offset: %s relation: ReadBuffer(%ld) failed",
801-
RelationGetRelationName(relation), (long)blocknumber);
802-
LockBuffer(buffer,BUFFER_LOCK_SHARE);
803-
p=BufferGetPage(buffer);
804-
offnum=PageGetMaxOffsetNumber(p);
805-
LockBuffer(buffer,BUFFER_LOCK_UNLOCK);
806-
ReleaseBuffer(buffer);
807-
returnoffnum;
808-
}
809-
810811

811812
/*
812813
*compute_minimal_stats() -- compute minimal column statistics
@@ -825,7 +826,7 @@ get_page_max_offset(Relation relation, BlockNumber blocknumber)
825826
*/
826827
staticvoid
827828
compute_minimal_stats(VacAttrStats*stats,
828-
TupleDesctupDesc,longtotalrows,
829+
TupleDesctupDesc,doubletotalrows,
829830
HeapTuple*rows,intnumrows)
830831
{
831832
inti;
@@ -1002,7 +1003,7 @@ compute_minimal_stats(VacAttrStats *stats,
10021003

10031004
if (f1<1)
10041005
f1=1;
1005-
term1=sqrt((double)totalrows / (double)numrows)*f1;
1006+
term1=sqrt(totalrows / (double)numrows)*f1;
10061007
stats->stadistinct=floor(term1+nmultiple+0.5);
10071008
}
10081009

@@ -1104,7 +1105,7 @@ compute_minimal_stats(VacAttrStats *stats,
11041105
*/
11051106
staticvoid
11061107
compute_scalar_stats(VacAttrStats*stats,
1107-
TupleDesctupDesc,longtotalrows,
1108+
TupleDesctupDesc,doubletotalrows,
11081109
HeapTuple*rows,intnumrows)
11091110
{
11101111
inti;
@@ -1298,7 +1299,7 @@ compute_scalar_stats(VacAttrStats *stats,
12981299

12991300
if (f1<1)
13001301
f1=1;
1301-
term1=sqrt((double)totalrows / (double)numrows)*f1;
1302+
term1=sqrt(totalrows / (double)numrows)*f1;
13021303
stats->stadistinct=floor(term1+nmultiple+0.5);
13031304
}
13041305

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp