diff options
Diffstat (limited to 'src/backend/utils/sort/tuplesort.c')
-rw-r--r-- | src/backend/utils/sort/tuplesort.c | 50 |
1 files changed, 35 insertions, 15 deletions
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index a9d5d79e033..af0109fda65 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -91,7 +91,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.62 2006/03/05 15:58:49 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.63 2006/03/07 19:06:50 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1384,7 +1384,8 @@ mergeruns(Tuplesortstate *state) /* * If we produced only one initial run (quite likely if the total data * volume is between 1X and 2X workMem), we can just use that tape as the - * finished output, rather than doing a useless merge. + * finished output, rather than doing a useless merge. (This obvious + * optimization is not in Knuth's algorithm.) */ if (state->currentRun == 1) { @@ -1401,33 +1402,51 @@ mergeruns(Tuplesortstate *state) for (;;) { - /* Step D5: merge runs onto tape[T] until tape[P] is empty */ - while (state->tp_runs[state->tapeRange - 1] || - state->tp_dummy[state->tapeRange - 1]) + /* + * At this point we know that tape[T] is empty. If there's just one + * (real or dummy) run left on each input tape, then only one merge + * pass remains. If we don't have to produce a materialized sorted + * tape, we can stop at this point and do the final merge on-the-fly. + */ + if (!state->randomAccess) { - bool allDummy = true; bool allOneRun = true; + Assert(state->tp_runs[state->tapeRange] == 0); for (tapenum = 0; tapenum < state->tapeRange; tapenum++) { - if (state->tp_dummy[tapenum] == 0) - allDummy = false; if (state->tp_runs[tapenum] + state->tp_dummy[tapenum] != 1) + { allOneRun = false; + break; + } } - - /* - * If we don't have to produce a materialized sorted tape, quit as - * soon as we're down to one real/dummy run per tape. - */ - if (!state->randomAccess && allOneRun) + if (allOneRun) { - Assert(!allDummy); + /* Tell logtape.c we won't be writing anymore */ + LogicalTapeSetForgetFreeSpace(state->tapeset); /* Initialize for the final merge pass */ beginmerge(state); state->status = TSS_FINALMERGE; return; } + } + + /* Step D5: merge runs onto tape[T] until tape[P] is empty */ + while (state->tp_runs[state->tapeRange - 1] || + state->tp_dummy[state->tapeRange - 1]) + { + bool allDummy = true; + + for (tapenum = 0; tapenum < state->tapeRange; tapenum++) + { + if (state->tp_dummy[tapenum] == 0) + { + allDummy = false; + break; + } + } + if (allDummy) { state->tp_dummy[state->tapeRange]++; @@ -1437,6 +1456,7 @@ mergeruns(Tuplesortstate *state) else mergeonerun(state); } + /* Step D6: decrease level */ if (--state->Level == 0) break; |