7
7
* Portions Copyright (c) 1994-5, Regents of the University of California
8
8
*
9
9
* IDENTIFICATION
10
- * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.195 2009/12/12 00:35:33 rhaas Exp $
10
+ * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.196 2009/12/15 04:57:47 rhaas Exp $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -125,6 +125,8 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
125
125
es .verbose = defGetBoolean (opt );
126
126
else if (strcmp (opt -> defname , "costs" ) == 0 )
127
127
es .costs = defGetBoolean (opt );
128
+ else if (strcmp (opt -> defname , "buffers" ) == 0 )
129
+ es .buffers = defGetBoolean (opt );
128
130
else if (strcmp (opt -> defname , "format" ) == 0 )
129
131
{
130
132
char * p = defGetString (opt );
@@ -150,6 +152,11 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
150
152
opt -> defname )));
151
153
}
152
154
155
+ if (es .buffers && !es .analyze )
156
+ ereport (ERROR ,
157
+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
158
+ errmsg ("EXPLAIN option BUFFERS requires ANALYZE" )));
159
+
153
160
/*
154
161
* Run parse analysis and rewrite. Note this also acquires sufficient
155
162
* locks on the source table(s).
@@ -339,6 +346,12 @@ ExplainOnePlan(PlannedStmt *plannedstmt, ExplainState *es,
339
346
instr_time starttime ;
340
347
double totaltime = 0 ;
341
348
int eflags ;
349
+ int instrument_option = 0 ;
350
+
351
+ if (es -> analyze )
352
+ instrument_option |= INSTRUMENT_TIMER ;
353
+ if (es -> buffers )
354
+ instrument_option |= INSTRUMENT_BUFFERS ;
342
355
343
356
/*
344
357
* Use a snapshot with an updated command ID to ensure this query sees
@@ -349,7 +362,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, ExplainState *es,
349
362
/* Create a QueryDesc requesting no output */
350
363
queryDesc = CreateQueryDesc (plannedstmt , queryString ,
351
364
GetActiveSnapshot (), InvalidSnapshot ,
352
- None_Receiver , params , es -> analyze );
365
+ None_Receiver , params , instrument_option );
353
366
354
367
INSTR_TIME_SET_CURRENT (starttime );
355
368
@@ -1042,6 +1055,84 @@ ExplainNode(Plan *plan, PlanState *planstate,
1042
1055
break ;
1043
1056
}
1044
1057
1058
+ /* Show buffer usage */
1059
+ if (es -> buffers )
1060
+ {
1061
+ const BufferUsage * usage = & planstate -> instrument -> bufusage ;
1062
+
1063
+ if (es -> format == EXPLAIN_FORMAT_TEXT )
1064
+ {
1065
+ bool has_shared = (usage -> shared_blks_hit > 0 ||
1066
+ usage -> shared_blks_read > 0 ||
1067
+ usage -> shared_blks_written );
1068
+ bool has_local = (usage -> local_blks_hit > 0 ||
1069
+ usage -> local_blks_read > 0 ||
1070
+ usage -> local_blks_written );
1071
+ bool has_temp = (usage -> temp_blks_read > 0 ||
1072
+ usage -> temp_blks_written );
1073
+
1074
+ /* Show only positive counter values. */
1075
+ if (has_shared || has_local || has_temp )
1076
+ {
1077
+ appendStringInfoSpaces (es -> str , es -> indent * 2 );
1078
+ appendStringInfoString (es -> str , "Buffers:" );
1079
+
1080
+ if (has_shared )
1081
+ {
1082
+ appendStringInfoString (es -> str , " shared" );
1083
+ if (usage -> shared_blks_hit > 0 )
1084
+ appendStringInfo (es -> str , " hit=%ld" ,
1085
+ usage -> shared_blks_hit );
1086
+ if (usage -> shared_blks_read > 0 )
1087
+ appendStringInfo (es -> str , " read=%ld" ,
1088
+ usage -> shared_blks_read );
1089
+ if (usage -> shared_blks_written > 0 )
1090
+ appendStringInfo (es -> str , " written=%ld" ,
1091
+ usage -> shared_blks_written );
1092
+ if (has_local || has_temp )
1093
+ appendStringInfoChar (es -> str , ',' );
1094
+ }
1095
+ if (has_local )
1096
+ {
1097
+ appendStringInfoString (es -> str , " local" );
1098
+ if (usage -> local_blks_hit > 0 )
1099
+ appendStringInfo (es -> str , " hit=%ld" ,
1100
+ usage -> local_blks_hit );
1101
+ if (usage -> local_blks_read > 0 )
1102
+ appendStringInfo (es -> str , " read=%ld" ,
1103
+ usage -> local_blks_read );
1104
+ if (usage -> local_blks_written > 0 )
1105
+ appendStringInfo (es -> str , " written=%ld" ,
1106
+ usage -> local_blks_written );
1107
+ if (has_temp )
1108
+ appendStringInfoChar (es -> str , ',' );
1109
+ }
1110
+ if (has_temp )
1111
+ {
1112
+ appendStringInfoString (es -> str , " temp" );
1113
+ if (usage -> temp_blks_read > 0 )
1114
+ appendStringInfo (es -> str , " read=%ld" ,
1115
+ usage -> temp_blks_read );
1116
+ if (usage -> temp_blks_written > 0 )
1117
+ appendStringInfo (es -> str , " written=%ld" ,
1118
+ usage -> temp_blks_written );
1119
+ }
1120
+ appendStringInfoChar (es -> str , '\n' );
1121
+ }
1122
+ }
1123
+ else
1124
+ {
1125
+ ExplainPropertyLong ("Shared Hit Blocks" , usage -> shared_blks_hit , es );
1126
+ ExplainPropertyLong ("Shared Read Blocks" , usage -> shared_blks_read , es );
1127
+ ExplainPropertyLong ("Shared Written Blocks" , usage -> shared_blks_written , es );
1128
+ ExplainPropertyLong ("Local Hit Blocks" , usage -> local_blks_hit , es );
1129
+ ExplainPropertyLong ("Local Read Blocks" , usage -> local_blks_read , es );
1130
+ ExplainPropertyLong ("Local Written Blocks" , usage -> local_blks_written , es );
1131
+ ExplainPropertyLong ("Temp Read Blocks" , usage -> temp_blks_read , es );
1132
+ ExplainPropertyLong ("Temp Written Blocks" , usage -> temp_blks_written , es );
1133
+ }
1134
+ }
1135
+
1045
1136
/* Get ready to display the child plans */
1046
1137
haschildren = plan -> initPlan ||
1047
1138
outerPlan (plan ) ||
0 commit comments