91
91
* Portions Copyright (c) 1994, Regents of the University of California
92
92
*
93
93
* IDENTIFICATION
94
- * $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.62 2006/03/05 15:58:49 momjian Exp $
94
+ * $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.63 2006/03/07 19:06:50 tgl Exp $
95
95
*
96
96
*-------------------------------------------------------------------------
97
97
*/
@@ -1384,7 +1384,8 @@ mergeruns(Tuplesortstate *state)
1384
1384
/*
1385
1385
* If we produced only one initial run (quite likely if the total data
1386
1386
* volume is between 1X and 2X workMem), we can just use that tape as the
1387
- * finished output, rather than doing a useless merge.
1387
+ * finished output, rather than doing a useless merge. (This obvious
1388
+ * optimization is not in Knuth's algorithm.)
1388
1389
*/
1389
1390
if (state -> currentRun == 1 )
1390
1391
{
@@ -1401,33 +1402,51 @@ mergeruns(Tuplesortstate *state)
1401
1402
1402
1403
for (;;)
1403
1404
{
1404
- /* Step D5: merge runs onto tape[T] until tape[P] is empty */
1405
- while (state -> tp_runs [state -> tapeRange - 1 ] ||
1406
- state -> tp_dummy [state -> tapeRange - 1 ])
1405
+ /*
1406
+ * At this point we know that tape[T] is empty. If there's just one
1407
+ * (real or dummy) run left on each input tape, then only one merge
1408
+ * pass remains. If we don't have to produce a materialized sorted
1409
+ * tape, we can stop at this point and do the final merge on-the-fly.
1410
+ */
1411
+ if (!state -> randomAccess )
1407
1412
{
1408
- bool allDummy = true;
1409
1413
bool allOneRun = true;
1410
1414
1415
+ Assert (state -> tp_runs [state -> tapeRange ] == 0 );
1411
1416
for (tapenum = 0 ; tapenum < state -> tapeRange ; tapenum ++ )
1412
1417
{
1413
- if (state -> tp_dummy [tapenum ] == 0 )
1414
- allDummy = false;
1415
1418
if (state -> tp_runs [tapenum ] + state -> tp_dummy [tapenum ] != 1 )
1419
+ {
1416
1420
allOneRun = false;
1421
+ break ;
1422
+ }
1417
1423
}
1418
-
1419
- /*
1420
- * If we don't have to produce a materialized sorted tape, quit as
1421
- * soon as we're down to one real/dummy run per tape.
1422
- */
1423
- if (!state -> randomAccess && allOneRun )
1424
+ if (allOneRun )
1424
1425
{
1425
- Assert (!allDummy );
1426
+ /* Tell logtape.c we won't be writing anymore */
1427
+ LogicalTapeSetForgetFreeSpace (state -> tapeset );
1426
1428
/* Initialize for the final merge pass */
1427
1429
beginmerge (state );
1428
1430
state -> status = TSS_FINALMERGE ;
1429
1431
return ;
1430
1432
}
1433
+ }
1434
+
1435
+ /* Step D5: merge runs onto tape[T] until tape[P] is empty */
1436
+ while (state -> tp_runs [state -> tapeRange - 1 ] ||
1437
+ state -> tp_dummy [state -> tapeRange - 1 ])
1438
+ {
1439
+ bool allDummy = true;
1440
+
1441
+ for (tapenum = 0 ; tapenum < state -> tapeRange ; tapenum ++ )
1442
+ {
1443
+ if (state -> tp_dummy [tapenum ] == 0 )
1444
+ {
1445
+ allDummy = false;
1446
+ break ;
1447
+ }
1448
+ }
1449
+
1431
1450
if (allDummy )
1432
1451
{
1433
1452
state -> tp_dummy [state -> tapeRange ]++ ;
@@ -1437,6 +1456,7 @@ mergeruns(Tuplesortstate *state)
1437
1456
else
1438
1457
mergeonerun (state );
1439
1458
}
1459
+
1440
1460
/* Step D6: decrease level */
1441
1461
if (-- state -> Level == 0 )
1442
1462
break ;
0 commit comments