Skip to content

Commit d2a4a40

Browse files
committed
Add a line to the EXPLAIN ANALYZE output for a Sort node, showing the
actual sort strategy and amount of space used. By popular demand.
1 parent c746472 commit d2a4a40

File tree

3 files changed

+94
-3
lines changed

3 files changed

+94
-3
lines changed

src/backend/commands/explain.c

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994-5, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.162 2007/04/27 22:05:47 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.163 2007/05/04 21:29:52 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -30,6 +30,7 @@
3030
#include "utils/builtins.h"
3131
#include "utils/guc.h"
3232
#include "utils/lsyscache.h"
33+
#include "utils/tuplesort.h"
3334

3435

3536
typedef struct ExplainState
@@ -58,6 +59,8 @@ static void show_upper_qual(List *qual, const char *qlabel, Plan *plan,
5859
static void show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols,
5960
const char *qlabel,
6061
StringInfo str, int indent, ExplainState *es);
62+
static void show_sort_info(SortState *sortstate,
63+
StringInfo str, int indent, ExplainState *es);
6164

6265
/*
6366
* ExplainQuery -
@@ -818,6 +821,8 @@ explain_outNode(StringInfo str,
818821
((Sort *) plan)->sortColIdx,
819822
"Sort Key",
820823
str, indent, es);
824+
show_sort_info((SortState *) planstate,
825+
str, indent, es);
821826
break;
822827
case T_Result:
823828
show_upper_qual((List *) ((Result *) plan)->resconstantqual,
@@ -1123,3 +1128,25 @@ show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols,
11231128

11241129
appendStringInfo(str, "\n");
11251130
}
1131+
1132+
/*
1133+
* If it's EXPLAIN ANALYZE, show tuplesort explain info for a sort node
1134+
*/
1135+
static void
1136+
show_sort_info(SortState *sortstate,
1137+
StringInfo str, int indent, ExplainState *es)
1138+
{
1139+
Assert(IsA(sortstate, SortState));
1140+
if (es->printAnalyze && sortstate->sort_Done &&
1141+
sortstate->tuplesortstate != NULL)
1142+
{
1143+
char *sortinfo;
1144+
int i;
1145+
1146+
sortinfo = tuplesort_explain((Tuplesortstate *) sortstate->tuplesortstate);
1147+
for (i = 0; i < indent; i++)
1148+
appendStringInfo(str, " ");
1149+
appendStringInfo(str, " %s\n", sortinfo);
1150+
pfree(sortinfo);
1151+
}
1152+
}

src/backend/utils/sort/tuplesort.c

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@
9191
* Portions Copyright (c) 1994, Regents of the University of California
9292
*
9393
* IDENTIFICATION
94-
* $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.75 2007/05/04 01:13:44 tgl Exp $
94+
* $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.76 2007/05/04 21:29:53 tgl Exp $
9595
*
9696
*-------------------------------------------------------------------------
9797
*/
@@ -196,6 +196,7 @@ struct Tuplesortstate
196196
bool randomAccess; /* did caller request random access? */
197197
bool bounded; /* did caller specify a maximum number of
198198
* tuples to return? */
199+
bool boundUsed; /* true if we made use of a bounded heap */
199200
int bound; /* if bounded, the maximum number of tuples */
200201
long availMem; /* remaining memory available, in bytes */
201202
long allowedMem; /* total memory allowed, in bytes */
@@ -505,6 +506,8 @@ tuplesort_begin_common(int workMem, bool randomAccess)
505506

506507
state->status = TSS_INITIAL;
507508
state->randomAccess = randomAccess;
509+
state->bounded = false;
510+
state->boundUsed = false;
508511
state->allowedMem = workMem * 1024L;
509512
state->availMem = state->allowedMem;
510513
state->sortcontext = sortcontext;
@@ -2113,6 +2116,64 @@ tuplesort_restorepos(Tuplesortstate *state)
21132116
MemoryContextSwitchTo(oldcontext);
21142117
}
21152118

2119+
/*
2120+
* tuplesort_explain - produce a line of information for EXPLAIN ANALYZE
2121+
*
2122+
* This can be called after tuplesort_performsort() finishes to obtain
2123+
* printable summary information about how the sort was performed.
2124+
*
2125+
* The result is a palloc'd string.
2126+
*/
2127+
char *
2128+
tuplesort_explain(Tuplesortstate *state)
2129+
{
2130+
char *result = (char *) palloc(100);
2131+
long spaceUsed;
2132+
2133+
/*
2134+
* Note: it might seem we should print both memory and disk usage for a
2135+
* disk-based sort. However, the current code doesn't track memory space
2136+
* accurately once we have begun to return tuples to the caller (since
2137+
* we don't account for pfree's the caller is expected to do), so we
2138+
* cannot rely on availMem in a disk sort. This does not seem worth the
2139+
* overhead to fix. Is it worth creating an API for the memory context
2140+
* code to tell us how much is actually used in sortcontext?
2141+
*/
2142+
if (state->tapeset)
2143+
spaceUsed = LogicalTapeSetBlocks(state->tapeset) * (BLCKSZ / 1024);
2144+
else
2145+
spaceUsed = (state->allowedMem - state->availMem + 1023) / 1024;
2146+
2147+
switch (state->status)
2148+
{
2149+
case TSS_SORTEDINMEM:
2150+
if (state->boundUsed)
2151+
snprintf(result, 100,
2152+
"Sort Method: top-N heapsort Memory: %ldkB",
2153+
spaceUsed);
2154+
else
2155+
snprintf(result, 100,
2156+
"Sort Method: quicksort Memory: %ldkB",
2157+
spaceUsed);
2158+
break;
2159+
case TSS_SORTEDONTAPE:
2160+
snprintf(result, 100,
2161+
"Sort Method: external sort Disk: %ldkB",
2162+
spaceUsed);
2163+
break;
2164+
case TSS_FINALMERGE:
2165+
snprintf(result, 100,
2166+
"Sort Method: external merge Disk: %ldkB",
2167+
spaceUsed);
2168+
break;
2169+
default:
2170+
snprintf(result, 100, "sort still in progress");
2171+
break;
2172+
}
2173+
2174+
return result;
2175+
}
2176+
21162177

21172178
/*
21182179
* Heap manipulation routines, per Knuth's Algorithm 5.2.3H.
@@ -2216,6 +2277,7 @@ sort_bounded_heap(Tuplesortstate *state)
22162277
REVERSEDIRECTION(state);
22172278

22182279
state->status = TSS_SORTEDINMEM;
2280+
state->boundUsed = true;
22192281
}
22202282

22212283
/*

src/include/utils/tuplesort.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
1414
* Portions Copyright (c) 1994, Regents of the University of California
1515
*
16-
* $PostgreSQL: pgsql/src/include/utils/tuplesort.h,v 1.26 2007/05/04 01:13:45 tgl Exp $
16+
* $PostgreSQL: pgsql/src/include/utils/tuplesort.h,v 1.27 2007/05/04 21:29:53 tgl Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -74,6 +74,8 @@ extern bool tuplesort_getdatum(Tuplesortstate *state, bool forward,
7474

7575
extern void tuplesort_end(Tuplesortstate *state);
7676

77+
extern char *tuplesort_explain(Tuplesortstate *state);
78+
7779
extern int tuplesort_merge_order(long allowedMem);
7880

7981
/*

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy