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

Commit89d00cb

Browse files
committed
Allow pgbench to use a scale larger than 21474.
Beyond 21474, the number of accounts exceed the range for int4. Change theinitialization code to use bigint for account id columns when scale is largeenough, and switch to using int64s for the variables in pgbench code. Thethreshold where we switch to bigints is set at 20000, because that's easierto remember and document than 21474, and ensures that there is some headroomwhen int4s are used.Greg Smith, with various changes by Euler Taveira de Oliveira, GurjeetSingh and Satoshi Nagayasu.
1 parentc9d7dba commit89d00cb

File tree

2 files changed

+128
-32
lines changed

2 files changed

+128
-32
lines changed

‎contrib/pgbench/pgbench.c

Lines changed: 123 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,15 @@ char *index_tablespace = NULL;
151151
#definentellers10
152152
#definenaccounts100000
153153

154+
/*
155+
* The scale factor at/beyond which 32bit integers are incapable of storing
156+
* 64bit values.
157+
*
158+
* Although the actual threshold is 21474, we use 20000 because it is easier to
159+
* document and remember, and isn't that far away from the real threshold.
160+
*/
161+
#defineSCALE_32BIT_THRESHOLD 20000
162+
154163
booluse_log;/* log transaction latencies to a file */
155164
booluse_quiet;/* quiet logging onto stderr */
156165
boolis_connect;/* establish connection for each transaction */
@@ -403,9 +412,77 @@ usage(void)
403412
progname,progname);
404413
}
405414

415+
/*
416+
* strtoint64 -- convert a string to 64-bit integer
417+
*
418+
* This function is a modified version of scanint8() from
419+
* src/backend/utils/adt/int8.c.
420+
*/
421+
staticint64
422+
strtoint64(constchar*str)
423+
{
424+
constchar*ptr=str;
425+
int64result=0;
426+
intsign=1;
427+
428+
/*
429+
* Do our own scan, rather than relying on sscanf which might be broken
430+
* for long long.
431+
*/
432+
433+
/* skip leading spaces */
434+
while (*ptr&&isspace((unsignedchar)*ptr))
435+
ptr++;
436+
437+
/* handle sign */
438+
if (*ptr=='-')
439+
{
440+
ptr++;
441+
442+
/*
443+
* Do an explicit check for INT64_MIN.Ugly though this is, it's
444+
* cleaner than trying to get the loop below to handle it portably.
445+
*/
446+
if (strncmp(ptr,"9223372036854775808",19)==0)
447+
{
448+
result=-INT64CONST(0x7fffffffffffffff)-1;
449+
ptr+=19;
450+
gotogotdigits;
451+
}
452+
sign=-1;
453+
}
454+
elseif (*ptr=='+')
455+
ptr++;
456+
457+
/* require at least one digit */
458+
if (!isdigit((unsignedchar)*ptr))
459+
fprintf(stderr,"invalid input syntax for integer: \"%s\"\n",str);
460+
461+
/* process digits */
462+
while (*ptr&&isdigit((unsignedchar)*ptr))
463+
{
464+
int64tmp=result*10+ (*ptr++-'0');
465+
466+
if ((tmp /10)!=result)/* overflow? */
467+
fprintf(stderr,"value \"%s\" is out of range for type bigint\n",str);
468+
result=tmp;
469+
}
470+
471+
gotdigits:
472+
473+
/* allow trailing whitespace, but not other trailing chars */
474+
while (*ptr!='\0'&&isspace((unsignedchar)*ptr))
475+
ptr++;
476+
477+
if (*ptr!='\0')
478+
fprintf(stderr,"invalid input syntax for integer: \"%s\"\n",str);
479+
480+
return ((sign<0) ?-result :result);
481+
}
482+
406483
/* random number generator: uniform distribution from min to max inclusive */
407-
staticint
408-
getrand(TState*thread,intmin,intmax)
484+
staticint64
485+
getrand(TState*thread,int64min,int64max)
409486
{
410487
/*
411488
* Odd coding is so that min and max have approximately the same chance of
@@ -416,7 +493,7 @@ getrand(TState *thread, int min, int max)
416493
* protected by a mutex, and therefore a bottleneck on machines with many
417494
* CPUs.
418495
*/
419-
returnmin+ (int) ((max-min+1)*pg_erand48(thread->random_state));
496+
returnmin+ (int64) ((max-min+1)*pg_erand48(thread->random_state));
420497
}
421498

422499
/* call PQexec() and exit() on failure */
@@ -960,7 +1037,7 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile)
9601037
if (commands[st->state]==NULL)
9611038
{
9621039
st->state=0;
963-
st->use_file=getrand(thread,0,num_files-1);
1040+
st->use_file=(int)getrand(thread,0,num_files-1);
9641041
commands=sql_files[st->use_file];
9651042
}
9661043
}
@@ -1080,7 +1157,7 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile)
10801157
if (pg_strcasecmp(argv[0],"setrandom")==0)
10811158
{
10821159
char*var;
1083-
intmin,
1160+
int64min,
10841161
max;
10851162
charres[64];
10861163

@@ -1092,10 +1169,10 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile)
10921169
st->ecnt++;
10931170
return true;
10941171
}
1095-
min=atoi(var);
1172+
min=strtoint64(var);
10961173
}
10971174
else
1098-
min=atoi(argv[2]);
1175+
min=strtoint64(argv[2]);
10991176

11001177
#ifdefNOT_USED
11011178
if (min<0)
@@ -1114,10 +1191,10 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile)
11141191
st->ecnt++;
11151192
return true;
11161193
}
1117-
max=atoi(var);
1194+
max=strtoint64(var);
11181195
}
11191196
else
1120-
max=atoi(argv[3]);
1197+
max=strtoint64(argv[3]);
11211198

11221199
if (max<min)
11231200
{
@@ -1127,8 +1204,8 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile)
11271204
}
11281205

11291206
/*
1130-
* getrand()neeeds to be able to subtract max from min and add
1131-
* one the result without overflowing.Since we know max > min,
1207+
* getrand()needs to be able to subtract max from min and add
1208+
* onetothe result without overflowing.Since we know max > min,
11321209
* we can detect overflow just by checking for a negative result.
11331210
* But we must check both that the subtraction doesn't overflow,
11341211
* and that adding one to the result doesn't overflow either.
@@ -1141,9 +1218,9 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile)
11411218
}
11421219

11431220
#ifdefDEBUG
1144-
printf("min:%dmax:%drandom:%d\n",min,max,getrand(thread,min,max));
1221+
printf("min:"INT64_FORMAT"max:"INT64_FORMAT"random:"INT64_FORMAT"\n",min,max,getrand(thread,min,max));
11451222
#endif
1146-
snprintf(res,sizeof(res),"%d",getrand(thread,min,max));
1223+
snprintf(res,sizeof(res),INT64_FORMAT,getrand(thread,min,max));
11471224

11481225
if (!putVariable(st,argv[0],argv[1],res))
11491226
{
@@ -1156,7 +1233,7 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile)
11561233
elseif (pg_strcasecmp(argv[0],"set")==0)
11571234
{
11581235
char*var;
1159-
intope1,
1236+
int64ope1,
11601237
ope2;
11611238
charres[64];
11621239

@@ -1168,13 +1245,13 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile)
11681245
st->ecnt++;
11691246
return true;
11701247
}
1171-
ope1=atoi(var);
1248+
ope1=strtoint64(var);
11721249
}
11731250
else
1174-
ope1=atoi(argv[2]);
1251+
ope1=strtoint64(argv[2]);
11751252

11761253
if (argc<5)
1177-
snprintf(res,sizeof(res),"%d",ope1);
1254+
snprintf(res,sizeof(res),INT64_FORMAT,ope1);
11781255
else
11791256
{
11801257
if (*argv[4]==':')
@@ -1185,17 +1262,17 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile)
11851262
st->ecnt++;
11861263
return true;
11871264
}
1188-
ope2=atoi(var);
1265+
ope2=strtoint64(var);
11891266
}
11901267
else
1191-
ope2=atoi(argv[4]);
1268+
ope2=strtoint64(argv[4]);
11921269

11931270
if (strcmp(argv[3],"+")==0)
1194-
snprintf(res,sizeof(res),"%d",ope1+ope2);
1271+
snprintf(res,sizeof(res),INT64_FORMAT,ope1+ope2);
11951272
elseif (strcmp(argv[3],"-")==0)
1196-
snprintf(res,sizeof(res),"%d",ope1-ope2);
1273+
snprintf(res,sizeof(res),INT64_FORMAT,ope1-ope2);
11971274
elseif (strcmp(argv[3],"*")==0)
1198-
snprintf(res,sizeof(res),"%d",ope1*ope2);
1275+
snprintf(res,sizeof(res),INT64_FORMAT,ope1*ope2);
11991276
elseif (strcmp(argv[3],"/")==0)
12001277
{
12011278
if (ope2==0)
@@ -1204,7 +1281,7 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile)
12041281
st->ecnt++;
12051282
return true;
12061283
}
1207-
snprintf(res,sizeof(res),"%d",ope1 /ope2);
1284+
snprintf(res,sizeof(res),INT64_FORMAT,ope1 /ope2);
12081285
}
12091286
else
12101287
{
@@ -1311,6 +1388,15 @@ disconnect_all(CState *state, int length)
13111388
staticvoid
13121389
init(boolis_no_vacuum)
13131390
{
1391+
1392+
/* The scale factor at/beyond which 32bit integers are incapable of storing
1393+
* 64bit values.
1394+
*
1395+
* Although the actual threshold is 21474, we use 20000 because it is easier to
1396+
* document and remember, and isn't that far away from the real threshold.
1397+
*/
1398+
#defineSCALE_32BIT_THRESHOLD 20000
1399+
13141400
/*
13151401
* Note: TPC-B requires at least 100 bytes per row, and the "filler"
13161402
* fields in these table declarations were intended to comply with that.
@@ -1329,7 +1415,9 @@ init(bool is_no_vacuum)
13291415
structddlinfoDDLs[]= {
13301416
{
13311417
"pgbench_history",
1332-
"tid int,bid int,aid int,delta int,mtime timestamp,filler char(22)",
1418+
scale >=SCALE_32BIT_THRESHOLD
1419+
?"tid int,bid int,aid bigint,delta int,mtime timestamp,filler char(22)"
1420+
:"tid int,bid int,aid int,delta int,mtime timestamp,filler char(22)",
13331421
0
13341422
},
13351423
{
@@ -1339,7 +1427,9 @@ init(bool is_no_vacuum)
13391427
},
13401428
{
13411429
"pgbench_accounts",
1342-
"aid int not null,bid int,abalance int,filler char(84)",
1430+
scale >=SCALE_32BIT_THRESHOLD
1431+
?"aid bigint not null,bid int,abalance int,filler char(84)"
1432+
:"aid int not null,bid int,abalance int,filler char(84)",
13431433
1
13441434
},
13451435
{
@@ -1365,6 +1455,7 @@ init(bool is_no_vacuum)
13651455
PGresult*res;
13661456
charsql[256];
13671457
inti;
1458+
int64k;
13681459

13691460
/* used to track elapsed time and estimate of the remaining time */
13701461
instr_timestart,diff;
@@ -1441,11 +1532,11 @@ init(bool is_no_vacuum)
14411532

14421533
INSTR_TIME_SET_CURRENT(start);
14431534

1444-
for (i=0;i<naccounts*scale;i++)
1535+
for (k=0;k<(int64)naccounts*scale;k++)
14451536
{
1446-
intj=i+1;
1537+
int64j=k+1;
14471538

1448-
snprintf(sql,256,"%d\t%d\t%d\t\n",j,i /naccounts+1,0);
1539+
snprintf(sql,256,INT64_FORMAT"\t"INT64_FORMAT"\t%d\t\n",j,k /naccounts+1,0);
14491540
if (PQputline(con,sql))
14501541
{
14511542
fprintf(stderr,"PQputline failed\n");
@@ -1462,8 +1553,8 @@ init(bool is_no_vacuum)
14621553
elapsed_sec=INSTR_TIME_GET_DOUBLE(diff);
14631554
remaining_sec= (scale*naccounts-j)*elapsed_sec /j;
14641555

1465-
fprintf(stderr,"%d of%d tuples (%d%%) done (elapsed %.2f s, remaining %.2f s).\n",
1466-
j,naccounts*scale,
1556+
fprintf(stderr,INT64_FORMAT" of"INT64_FORMAT" tuples (%d%%) done (elapsed %.2f s, remaining %.2f s).\n",
1557+
j,(int64)naccounts*scale,
14671558
(int) (((int64)j*100) / (naccounts*scale)),
14681559
elapsed_sec,remaining_sec);
14691560
}
@@ -1479,8 +1570,8 @@ init(bool is_no_vacuum)
14791570
/* have we reached the next interval (or end)? */
14801571
if ((j==scale*naccounts)|| (elapsed_sec >=log_interval*LOG_STEP_SECONDS)) {
14811572

1482-
fprintf(stderr,"%d of%d tuples (%d%%) done (elapsed %.2f s, remaining %.2f s).\n",
1483-
j,naccounts*scale,
1573+
fprintf(stderr,INT64_FORMAT" of"INT64_FORMAT" tuples (%d%%) done (elapsed %.2f s, remaining %.2f s).\n",
1574+
j,(int64)naccounts*scale,
14841575
(int) (((int64)j*100) / (naccounts*scale)),elapsed_sec,remaining_sec);
14851576

14861577
/* skip to the next interval */

‎doc/src/sgml/pgbench.sgml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,11 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
185185
Multiply the number of rows generated by the scale factor.
186186
For example, <literal>-s 100</> will create 10,000,000 rows
187187
in the <structname>pgbench_accounts</> table. Default is 1.
188+
When the scale is 20,000 or larger, the columns used to
189+
hold account identifiers (<structfield>aid</structfield> columns)
190+
will switch to using larger integers (<type>bigint</type>),
191+
in order to be big enough to hold the range of account
192+
identifiers.
188193
</para>
189194
</listitem>
190195
</varlistentry>

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp