|
108 | 108 | * code we determine the number of tapes M on the basis of workMem: we want
|
109 | 109 | * workMem/M to be large enough that we read a fair amount of data each time
|
110 | 110 | * we preread from a tape, so as to maintain the locality of access described
|
111 |
| - * above. Nonetheless, with large workMem we can have many tapes. |
| 111 | + * above. Nonetheless, with large workMem we can have many tapes (but not |
| 112 | + * too many -- see the comments in tuplesort_merge_order). |
112 | 113 | *
|
113 | 114 | *
|
114 | 115 | * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
|
@@ -247,6 +248,7 @@ typedef enum
|
247 | 248 | * tape during a preread cycle (see discussion at top of file).
|
248 | 249 | */
|
249 | 250 | #define MINORDER 6 /* minimum merge order */
|
| 251 | +#define MAXORDER 500 /* maximum merge order */ |
250 | 252 | #define TAPE_BUFFER_OVERHEAD (BLCKSZ * 3)
|
251 | 253 | #define MERGE_BUFFER_SIZE (BLCKSZ * 32)
|
252 | 254 |
|
@@ -2313,8 +2315,19 @@ tuplesort_merge_order(int64 allowedMem)
|
2313 | 2315 | mOrder = (allowedMem - TAPE_BUFFER_OVERHEAD) /
|
2314 | 2316 | (MERGE_BUFFER_SIZE + TAPE_BUFFER_OVERHEAD);
|
2315 | 2317 |
|
2316 |
| - /* Even in minimum memory, use at least a MINORDER merge */ |
| 2318 | + /* |
| 2319 | + * Even in minimum memory, use at least a MINORDER merge. On the other |
| 2320 | + * hand, even when we have lots of memory, do not use more than a MAXORDER |
| 2321 | + * merge. Tapes are pretty cheap, but they're not entirely free. Each |
| 2322 | + * additional tape reduces the amount of memory available to build runs, |
| 2323 | + * which in turn can cause the same sort to need more runs, which makes |
| 2324 | + * merging slower even if it can still be done in a single pass. Also, |
| 2325 | + * high order merges are quite slow due to CPU cache effects; it can be |
| 2326 | + * faster to pay the I/O cost of a polyphase merge than to perform a single |
| 2327 | + * merge pass across many hundreds of tapes. |
| 2328 | + */ |
2317 | 2329 | mOrder = Max(mOrder, MINORDER);
|
| 2330 | + mOrder = Min(mOrder, MAXORDER); |
2318 | 2331 |
|
2319 | 2332 | return mOrder;
|
2320 | 2333 | }
|
|
0 commit comments