1414 * Copyright (c) 2008-2010, PostgreSQL Global Development Group
1515 *
1616 * IDENTIFICATION
17- * $PostgreSQL: pgsql/contrib/pg_stat_statements/pg_stat_statements.c,v 1.11 2010/01/02 16:57:32 momjian Exp $
17+ * $PostgreSQL: pgsql/contrib/pg_stat_statements/pg_stat_statements.c,v 1.12 2010/01/08 00:38:19 itagaki Exp $
1818 *
1919 *-------------------------------------------------------------------------
2020 */
2626#include "catalog/pg_type.h"
2727#include "executor/executor.h"
2828#include "executor/instrument.h"
29+ #include "funcapi.h"
2930#include "mb/pg_wchar.h"
3031#include "miscadmin.h"
3132#include "pgstat.h"
@@ -44,7 +45,7 @@ PG_MODULE_MAGIC;
4445#define PGSS_DUMP_FILE "global/pg_stat_statements.stat"
4546
4647/* This constant defines the magic number in the stats file header */
47- static const uint32 PGSS_FILE_HEADER = 0x20081202 ;
48+ static const uint32 PGSS_FILE_HEADER = 0x20100108 ;
4849
4950/* XXX: Should USAGE_EXEC reflect execution time and/or buffer usage? */
5051#define USAGE_EXEC (duration )(1.0)
@@ -75,10 +76,18 @@ typedef struct pgssHashKey
7576 */
7677typedef struct Counters
7778{
78- int64 calls ;/* # of times executed */
79- double total_time ;/* total execution time in seconds */
80- int64 rows ;/* total # of retrieved or affected rows */
81- double usage ;/* usage factor */
79+ int64 calls ;/* # of times executed */
80+ double total_time ;/* total execution time in seconds */
81+ int64 rows ;/* total # of retrieved or affected rows */
82+ int64 shared_blks_hit ;/* # of shared buffer hits */
83+ int64 shared_blks_read ;/* # of shared disk blocks read */
84+ int64 shared_blks_written ;/* # of shared disk blocks written */
85+ int64 local_blks_hit ;/* # of local buffer hits */
86+ int64 local_blks_read ;/* # of local disk blocks read */
87+ int64 local_blks_written ;/* # of local disk blocks written */
88+ int64 temp_blks_read ;/* # of temp blocks read */
89+ int64 temp_blks_written ;/* # of temp blocks written */
90+ double usage ;/* usage factor */
8291}Counters ;
8392
8493/*
@@ -129,7 +138,8 @@ typedef enum
129138PGSS_TRACK_ALL /* all statements, including nested ones */
130139}PGSSTrackLevel ;
131140
132- static const struct config_enum_entry track_options []= {
141+ static const struct config_enum_entry track_options []=
142+ {
133143{"none" ,PGSS_TRACK_NONE , false},
134144{"top" ,PGSS_TRACK_TOP , false},
135145{"all" ,PGSS_TRACK_ALL , false},
@@ -169,7 +179,8 @@ static void pgss_ProcessUtility(Node *parsetree,
169179DestReceiver * dest ,char * completionTag );
170180static uint32 pgss_hash_fn (const void * key ,Size keysize );
171181static int pgss_match_fn (const void * key1 ,const void * key2 ,Size keysize );
172- static void pgss_store (const char * query ,double total_time ,uint64 rows );
182+ static void pgss_store (const char * query ,double total_time ,uint64 rows ,
183+ const BufferUsage * bufusage );
173184static Size pgss_memsize (void );
174185static pgssEntry * entry_alloc (pgssHashKey * key );
175186static void entry_dealloc (void );
@@ -558,7 +569,8 @@ pgss_ExecutorEnd(QueryDesc *queryDesc)
558569
559570pgss_store (queryDesc -> sourceText ,
560571queryDesc -> totaltime -> total ,
561- queryDesc -> estate -> es_processed );
572+ queryDesc -> estate -> es_processed ,
573+ & queryDesc -> totaltime -> bufusage );
562574}
563575
564576if (prev_ExecutorEnd )
@@ -580,7 +592,9 @@ pgss_ProcessUtility(Node *parsetree, const char *queryString,
580592instr_time start ;
581593instr_time duration ;
582594uint64 rows = 0 ;
595+ BufferUsage bufusage ;
583596
597+ bufusage = pgBufferUsage ;
584598INSTR_TIME_SET_CURRENT (start );
585599
586600nested_level ++ ;
@@ -609,7 +623,26 @@ pgss_ProcessUtility(Node *parsetree, const char *queryString,
609623sscanf (completionTag ,"COPY " UINT64_FORMAT ,& rows )!= 1 )
610624rows = 0 ;
611625
612- pgss_store (queryString ,INSTR_TIME_GET_DOUBLE (duration ),rows );
626+ /* calc differences of buffer counters. */
627+ bufusage .shared_blks_hit =
628+ pgBufferUsage .shared_blks_hit - bufusage .shared_blks_hit ;
629+ bufusage .shared_blks_read =
630+ pgBufferUsage .shared_blks_read - bufusage .shared_blks_read ;
631+ bufusage .shared_blks_written =
632+ pgBufferUsage .shared_blks_written - bufusage .shared_blks_written ;
633+ bufusage .local_blks_hit =
634+ pgBufferUsage .local_blks_hit - bufusage .local_blks_hit ;
635+ bufusage .local_blks_read =
636+ pgBufferUsage .local_blks_read - bufusage .local_blks_read ;
637+ bufusage .local_blks_written =
638+ pgBufferUsage .local_blks_written - bufusage .local_blks_written ;
639+ bufusage .temp_blks_read =
640+ pgBufferUsage .temp_blks_read - bufusage .temp_blks_read ;
641+ bufusage .temp_blks_written =
642+ pgBufferUsage .temp_blks_written - bufusage .temp_blks_written ;
643+
644+ pgss_store (queryString ,INSTR_TIME_GET_DOUBLE (duration ),rows ,
645+ & bufusage );
613646}
614647else
615648{
@@ -660,7 +693,8 @@ pgss_match_fn(const void *key1, const void *key2, Size keysize)
660693 * Store some statistics for a statement.
661694 */
662695static void
663- pgss_store (const char * query ,double total_time ,uint64 rows )
696+ pgss_store (const char * query ,double total_time ,uint64 rows ,
697+ const BufferUsage * bufusage )
664698{
665699pgssHashKey key ;
666700double usage ;
@@ -706,6 +740,14 @@ pgss_store(const char *query, double total_time, uint64 rows)
706740e -> counters .calls += 1 ;
707741e -> counters .total_time += total_time ;
708742e -> counters .rows += rows ;
743+ e -> counters .shared_blks_hit += bufusage -> shared_blks_hit ;
744+ e -> counters .shared_blks_read += bufusage -> shared_blks_read ;
745+ e -> counters .shared_blks_written += bufusage -> shared_blks_written ;
746+ e -> counters .local_blks_hit += bufusage -> local_blks_hit ;
747+ e -> counters .local_blks_read += bufusage -> local_blks_read ;
748+ e -> counters .local_blks_written += bufusage -> local_blks_written ;
749+ e -> counters .temp_blks_read += bufusage -> temp_blks_read ;
750+ e -> counters .temp_blks_written += bufusage -> temp_blks_written ;
709751e -> counters .usage += usage ;
710752SpinLockRelease (& e -> mutex );
711753}
@@ -727,7 +769,7 @@ pg_stat_statements_reset(PG_FUNCTION_ARGS)
727769PG_RETURN_VOID ();
728770}
729771
730- #define PG_STAT_STATEMENTS_COLS 6
772+ #define PG_STAT_STATEMENTS_COLS 14
731773
732774/*
733775 * Retrieve statement statistics.
@@ -761,23 +803,13 @@ pg_stat_statements(PG_FUNCTION_ARGS)
761803errmsg ("materialize mode required, but it is not " \
762804"allowed in this context" )));
763805
806+ /* Build a tuple descriptor for our result type */
807+ if (get_call_result_type (fcinfo ,NULL ,& tupdesc )!= TYPEFUNC_COMPOSITE )
808+ elog (ERROR ,"return type must be a row type" );
809+
764810per_query_ctx = rsinfo -> econtext -> ecxt_per_query_memory ;
765811oldcontext = MemoryContextSwitchTo (per_query_ctx );
766812
767- tupdesc = CreateTemplateTupleDesc (PG_STAT_STATEMENTS_COLS , false);
768- TupleDescInitEntry (tupdesc , (AttrNumber )1 ,"userid" ,
769- OIDOID ,-1 ,0 );
770- TupleDescInitEntry (tupdesc , (AttrNumber )2 ,"dbid" ,
771- OIDOID ,-1 ,0 );
772- TupleDescInitEntry (tupdesc , (AttrNumber )3 ,"query" ,
773- TEXTOID ,-1 ,0 );
774- TupleDescInitEntry (tupdesc , (AttrNumber )4 ,"calls" ,
775- INT8OID ,-1 ,0 );
776- TupleDescInitEntry (tupdesc , (AttrNumber )5 ,"total_time" ,
777- FLOAT8OID ,-1 ,0 );
778- TupleDescInitEntry (tupdesc , (AttrNumber )6 ,"rows" ,
779- INT8OID ,-1 ,0 );
780-
781813tupstore = tuplestore_begin_heap (true, false,work_mem );
782814rsinfo -> returnMode = SFRM_Materialize ;
783815rsinfo -> setResult = tupstore ;
@@ -829,6 +861,14 @@ pg_stat_statements(PG_FUNCTION_ARGS)
829861values [i ++ ]= Int64GetDatumFast (tmp .calls );
830862values [i ++ ]= Float8GetDatumFast (tmp .total_time );
831863values [i ++ ]= Int64GetDatumFast (tmp .rows );
864+ values [i ++ ]= Int64GetDatumFast (tmp .shared_blks_hit );
865+ values [i ++ ]= Int64GetDatumFast (tmp .shared_blks_read );
866+ values [i ++ ]= Int64GetDatumFast (tmp .shared_blks_written );
867+ values [i ++ ]= Int64GetDatumFast (tmp .local_blks_hit );
868+ values [i ++ ]= Int64GetDatumFast (tmp .local_blks_read );
869+ values [i ++ ]= Int64GetDatumFast (tmp .local_blks_written );
870+ values [i ++ ]= Int64GetDatumFast (tmp .temp_blks_read );
871+ values [i ++ ]= Int64GetDatumFast (tmp .temp_blks_written );
832872
833873Assert (i == PG_STAT_STATEMENTS_COLS );
834874