diff -rc postgresql-8.1beta2.orig/src/backend/catalog/system_views.sql postgresql-8.1beta2/src/backend/catalog/system_views.sql *** postgresql-8.1beta2.orig/src/backend/catalog/system_views.sql 2005-09-24 11:29:38.000000000 +0900 --- postgresql-8.1beta2/src/backend/catalog/system_views.sql 2005-09-24 14:27:18.000000000 +0900 *************** *** 320,325 **** --- 320,335 ---- WHERE pg_stat_get_backend_dbid(S.backendid) = D.oid AND pg_stat_get_backend_userid(S.backendid) = U.oid; + + CREATE VIEW pg_stat_sorts AS + SELECT pg_stat_get_sort_heap_all() as heap_all, + pg_stat_get_sort_index_all() as index_all, + pg_stat_get_sort_datum_all() as datum_all, + pg_stat_get_sort_heap_tape() as heap_tape, + pg_stat_get_sort_datum_tape() as datum_tape, + pg_stat_get_max_sort_size() as max_size; + + CREATE VIEW pg_stat_database AS SELECT D.oid AS datid, diff -rc postgresql-8.1beta2.orig/src/backend/postmaster/pgstat.c postgresql-8.1beta2/src/backend/postmaster/pgstat.c *** postgresql-8.1beta2.orig/src/backend/postmaster/pgstat.c 2005-09-24 11:29:39.000000000 +0900 --- postgresql-8.1beta2/src/backend/postmaster/pgstat.c 2005-09-24 14:42:09.000000000 +0900 *************** *** 120,125 **** --- 120,132 ---- static bool pgStatRunningInCollector = FALSE; + static long pgStatSortHeapAll = 0; + static long pgStatSortIndexAll = 0; + static long pgStatSortDatumAll = 0; + static long pgStatSortHeapTape = 0; + static long pgStatSortDatumTape = 0; + static Size pgStatSortMaxUsedSize = 0; + /* * Place where backends store per-table info to be sent to the collector. * We store shared relations separately from non-shared ones, to be able to *************** *** 823,828 **** --- 830,843 ---- return; } + elog(DEBUG1, "report: Sort statistics: [dbentry=%d]", MyDatabaseId); + elog(DEBUG1, "report: Sort statistics: heap(all)=%ld, index(all)=%ld, datum(all)=%ld", + pgStatSortHeapAll,pgStatSortIndexAll,pgStatSortDatumAll); + elog(DEBUG1, "report: Sort statistics: heap(tape)=%ld, datum(tape)=%ld", + pgStatSortHeapTape,pgStatSortDatumTape); + elog(DEBUG1, "report: Sort statistics: MaxSortSize=%ld", + pgStatSortMaxUsedSize); + /* * For each message buffer used during the last query set the header * fields and send it out. *************** *** 839,847 **** --- 854,877 ---- tsmsg->m_xact_commit = pgStatXactCommit; tsmsg->m_xact_rollback = pgStatXactRollback; + pgStatXactCommit = 0; pgStatXactRollback = 0; + tsmsg->m_sort_heap_all = pgStatSortHeapAll; + tsmsg->m_sort_index_all = pgStatSortIndexAll; + tsmsg->m_sort_datum_all = pgStatSortDatumAll; + tsmsg->m_sort_heap_tape = pgStatSortHeapTape; + tsmsg->m_sort_datum_tape = pgStatSortDatumTape; + tsmsg->m_sort_max_used_size = pgStatSortMaxUsedSize; + + pgStatSortHeapAll = 0; + pgStatSortIndexAll = 0; + pgStatSortDatumAll = 0; + pgStatSortHeapTape = 0; + pgStatSortDatumTape = 0; + pgStatSortMaxUsedSize = 0; + pgstat_setheader(&tsmsg->m_hdr, PGSTAT_MTYPE_TABSTAT); tsmsg->m_databaseid = MyDatabaseId; pgstat_send(tsmsg, len); *************** *** 2218,2223 **** --- 2248,2260 ---- result->destroy = 0; result->last_autovac_time = 0; + result->n_sort_heap_all = 0; + result->n_sort_index_all = 0; + result->n_sort_datum_all = 0; + result->n_sort_heap_tape = 0; + result->n_sort_datum_tape = 0; + result->sort_max_used_size = 0; + memset(&hash_ctl, 0, sizeof(hash_ctl)); hash_ctl.keysize = sizeof(Oid); hash_ctl.entrysize = sizeof(PgStat_StatTabEntry); *************** *** 3050,3055 **** --- 3087,3101 ---- dbentry->n_xact_commit += (PgStat_Counter) (msg->m_xact_commit); dbentry->n_xact_rollback += (PgStat_Counter) (msg->m_xact_rollback); + dbentry->n_sort_heap_all += (PgStat_Counter) (msg->m_sort_heap_all); + dbentry->n_sort_index_all += (PgStat_Counter) (msg->m_sort_index_all); + dbentry->n_sort_datum_all += (PgStat_Counter) (msg->m_sort_datum_all); + dbentry->n_sort_heap_tape += (PgStat_Counter) (msg->m_sort_heap_tape); + dbentry->n_sort_datum_tape += (PgStat_Counter) (msg->m_sort_datum_tape); + + if ( dbentry->sort_max_used_size < msg->m_sort_max_used_size ) + dbentry->sort_max_used_size = (Size)msg->m_sort_max_used_size; + /* * Process all table entries in the message. */ *************** *** 3229,3234 **** --- 3275,3287 ---- dbentry->n_blocks_hit = 0; dbentry->destroy = 0; + dbentry->n_sort_heap_all = 0; + dbentry->n_sort_index_all = 0; + dbentry->n_sort_datum_all = 0; + dbentry->n_sort_heap_tape = 0; + dbentry->n_sort_datum_tape = 0; + dbentry->sort_max_used_size = 0; + memset(&hash_ctl, 0, sizeof(hash_ctl)); hash_ctl.keysize = sizeof(Oid); hash_ctl.entrysize = sizeof(PgStat_StatTabEntry); *************** *** 3238,3240 **** --- 3291,3344 ---- &hash_ctl, HASH_ELEM | HASH_FUNCTION); } + + + void + pgstat_count_sort_heap_all() + { + pgStatSortHeapAll++; + + elog(DEBUG5, "pgstat_count_sort_heap_all(): %d", pgStatSortHeapAll); + } + + void + pgstat_count_sort_index_all() + { + pgStatSortIndexAll++; + + elog(DEBUG5, "pgstat_count_sort_index_all(): %d", pgStatSortIndexAll); + } + + void + pgstat_count_sort_datum_all() + { + pgStatSortDatumAll++; + + elog(DEBUG5, "pgstat_count_sort_datum_all(): %d", pgStatSortDatumAll); + } + + void + pgstat_count_sort_heap_tape() + { + pgStatSortHeapTape++; + + elog(DEBUG5, "pgstat_count_sort_heap_tape(): %d", pgStatSortHeapTape); + } + + void + pgstat_count_sort_datum_tape() + { + pgStatSortDatumTape++; + + elog(DEBUG5, "pgstat_count_sort_datum_tape(): %d", pgStatSortDatumTape); + } + + void + pgstat_count_sort_max_used_size(Size size) + { + if ( size>pgStatSortMaxUsedSize ) + pgStatSortMaxUsedSize = size; + + elog(DEBUG5, "pgstat_count_sort_max_used_size(): %ld", + pgStatSortMaxUsedSize); + } diff -rc postgresql-8.1beta2.orig/src/backend/utils/adt/pgstatfuncs.c postgresql-8.1beta2/src/backend/utils/adt/pgstatfuncs.c *** postgresql-8.1beta2.orig/src/backend/utils/adt/pgstatfuncs.c 2005-09-24 11:29:42.000000000 +0900 --- postgresql-8.1beta2/src/backend/utils/adt/pgstatfuncs.c 2005-09-24 14:36:27.000000000 +0900 *************** *** 53,58 **** --- 53,81 ---- extern Datum pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS); extern Datum pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS); + typedef enum SORT_TYPE { + HEAP_ALL, + INDEX_ALL, + DATUM_ALL, + HEAP_TAPE, + DATUM_TAPE + } SORT_TYPE; + + PG_FUNCTION_INFO_V1(pg_stat_get_sort_heap_all); + PG_FUNCTION_INFO_V1(pg_stat_get_sort_index_all); + PG_FUNCTION_INFO_V1(pg_stat_get_sort_datum_all); + PG_FUNCTION_INFO_V1(pg_stat_get_sort_heap_tape); + PG_FUNCTION_INFO_V1(pg_stat_get_sort_datum_tape); + PG_FUNCTION_INFO_V1(pg_stat_get_max_sort_size); + PG_FUNCTION_INFO_V1(pg_stat_get_prev_sort_size); + + extern Datum pg_stat_get_sort_heap_all(PG_FUNCTION_ARGS); + extern Datum pg_stat_get_sort_index_all(PG_FUNCTION_ARGS); + extern Datum pg_stat_get_sort_datum_all(PG_FUNCTION_ARGS); + extern Datum pg_stat_get_sort_heap_tape(PG_FUNCTION_ARGS); + extern Datum pg_stat_get_sort_datum_tape(PG_FUNCTION_ARGS); + extern Datum pg_stat_get_max_sort_size(PG_FUNCTION_ARGS); + extern Datum pg_stat_get_prev_sort_size(PG_FUNCTION_ARGS); Datum pg_stat_get_numscans(PG_FUNCTION_ARGS) *************** *** 562,564 **** --- 585,693 ---- PG_RETURN_INT64(result); } + + + static int64 + get_sort_stat_internal(SORT_TYPE type) + { + PgStat_StatDBEntry *dbentry; + int64 result = 0; + + Oid dbid = MyDatabaseId; + + if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) + result = -1; + else + switch (type) + { + case HEAP_ALL: + result = (int64) (dbentry->n_sort_heap_all); + break; + case INDEX_ALL: + result = (int64) (dbentry->n_sort_index_all); + break; + case DATUM_ALL: + result = (int64) (dbentry->n_sort_datum_all); + break; + case HEAP_TAPE: + result = (int64) (dbentry->n_sort_heap_tape); + break; + case DATUM_TAPE: + result = (int64) (dbentry->n_sort_datum_tape); + break; + default: + elog(ERROR, "get_sort_stat_internal: unexpected type."); + break; + } + + if ( dbentry ) + { + elog(DEBUG5, "get_sort_stat_internal(): [dbentry=%d]", dbentry->databaseid); + elog(DEBUG5, "get_sort_stat_internal(): heap(all)=%ld, index(all)=%ld, datum(all)=%ld", + dbentry->n_sort_heap_all, + dbentry->n_sort_index_all, + dbentry->n_sort_datum_all); + elog(DEBUG5, "get_sort_stat_internal(): heap(tape)=%ld, datum(tape)=%ld", + dbentry->n_sort_heap_tape, + dbentry->n_sort_datum_tape); + elog(DEBUG5, "get_sort_stat_internal(): MaxSortSize=%ld", + dbentry->sort_max_used_size); + } + + return result; + } + + + Datum + pg_stat_get_sort_heap_all(PG_FUNCTION_ARGS) + { + PG_RETURN_INT64(get_sort_stat_internal(HEAP_ALL)); + } + + Datum + pg_stat_get_sort_index_all(PG_FUNCTION_ARGS) + { + PG_RETURN_INT64(get_sort_stat_internal(INDEX_ALL)); + } + + Datum + pg_stat_get_sort_datum_all(PG_FUNCTION_ARGS) + { + PG_RETURN_INT64(get_sort_stat_internal(DATUM_ALL)); + } + + Datum + pg_stat_get_sort_heap_tape(PG_FUNCTION_ARGS) + { + PG_RETURN_INT64(get_sort_stat_internal(HEAP_TAPE)); + } + + Datum + pg_stat_get_sort_datum_tape(PG_FUNCTION_ARGS) + { + PG_RETURN_INT64(get_sort_stat_internal(DATUM_TAPE)); + } + + Datum + pg_stat_get_max_sort_size(PG_FUNCTION_ARGS) + { + PgStat_StatDBEntry *dbentry; + Oid dbid; + int64 result; + + // dbid = PG_GETARG_OID(0); + dbid = MyDatabaseId; + + if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) + result = -1; + else + result = (int64) (dbentry->sort_max_used_size); + + PG_RETURN_INT64(result); + } + + Datum + pg_stat_get_prev_sort_size(PG_FUNCTION_ARGS) + { + PG_RETURN_INT64(tuplesort_get_prev_size()); + } diff -rc postgresql-8.1beta2.orig/src/backend/utils/sort/tuplesort.c postgresql-8.1beta2/src/backend/utils/sort/tuplesort.c *** postgresql-8.1beta2.orig/src/backend/utils/sort/tuplesort.c 2005-09-24 11:29:46.000000000 +0900 --- postgresql-8.1beta2/src/backend/utils/sort/tuplesort.c 2005-09-24 14:35:27.000000000 +0900 *************** *** 283,288 **** --- 283,290 ---- /* we need typelen and byval in order to know how to copy the Datums. */ int datumTypeLen; bool datumTypeByVal; + + Size usedSize; }; #define COMPARETUP(state,a,b) ((*(state)->comparetup) (state, a, b)) *************** *** 395,400 **** --- 397,404 ---- static Tuplesortstate *qsort_tuplesortstate; + static Size prevSortSize = 0; + /* * tuplesort_begin_xxx * *************** *** 442,447 **** --- 446,453 ---- state->result_tape = -1; /* flag that result tape has not been * formed */ + state->usedSize = 0; + return state; } *************** *** 489,494 **** --- 495,502 ---- (Datum) 0); } + pgstat_count_sort_heap_all(); + return state; } *************** *** 509,514 **** --- 517,524 ---- state->indexScanKey = _bt_mkscankey_nodata(indexRel); state->enforceUnique = enforceUnique; + pgstat_count_sort_index_all(); + return state; } *************** *** 540,545 **** --- 550,557 ---- state->datumTypeLen = typlen; state->datumTypeByVal = typbyval; + pgstat_count_sort_datum_all(); + return state; } *************** *** 553,558 **** --- 565,577 ---- { int i; + pgstat_count_sort_max_used_size(state->usedSize); + + elog(DEBUG5, "tuplesort_end: usedSize=%ld, tape=%d", + state->usedSize, (state->tapeset ? 1 : 0)); + + prevSortSize = state->usedSize; + if (state->tapeset) LogicalTapeSetClose(state->tapeset); if (state->memtuples) *************** *** 1027,1032 **** --- 1046,1057 ---- state->Level = 1; state->destTape = 0; + /* If not a datum sort, it's a heap sort */ + if ( state->datumType == InvalidOid ) + pgstat_count_sort_heap_tape(); + else + pgstat_count_sort_datum_tape(); + state->status = TSS_BUILDRUNS; } *************** *** 1952,1957 **** --- 1977,1983 ---- tuple = heap_copytuple(tuple); USEMEM(state, GetMemoryChunkSpace(tuple)); + state->usedSize += GetMemoryChunkSpace(tuple); return (void *) tuple; } *************** *** 2111,2116 **** --- 2137,2143 ---- newtuple = (IndexTuple) palloc(tuplen); USEMEM(state, GetMemoryChunkSpace(newtuple)); + state->usedSize += GetMemoryChunkSpace(newtuple); memcpy(newtuple, tuple, tuplen); *************** *** 2228,2230 **** --- 2255,2264 ---- MAXALIGN(sizeof(DatumTuple))); return (void *) tuple; } + + Size + tuplesort_get_prev_size() + { + return prevSortSize; + } + diff -rc postgresql-8.1beta2.orig/src/include/catalog/pg_proc.h postgresql-8.1beta2/src/include/catalog/pg_proc.h *** postgresql-8.1beta2.orig/src/include/catalog/pg_proc.h 2005-09-24 11:29:48.000000000 +0900 --- postgresql-8.1beta2/src/include/catalog/pg_proc.h 2005-09-24 14:32:59.000000000 +0900 *************** *** 2863,2868 **** --- 2863,2883 ---- DATA(insert OID = 1945 ( pg_stat_get_db_blocks_hit PGNSP PGUID 12 f f t f s 1 20 "26" _null_ _null_ _null_ pg_stat_get_db_blocks_hit - _null_ )); DESCR("Statistics: Blocks found in cache for database"); + DATA(insert OID = 1971 ( pg_stat_get_sort_heap_all PGNSP PGUID 12 f f t f s 0 20 "" _null_ _null_ _null_ pg_stat_get_sort_heap_all - _null_ )); + DESCR("Statistics: pg_stat_get_sort_heap_all"); + DATA(insert OID = 1972 ( pg_stat_get_sort_index_all PGNSP PGUID 12 f f t f s 0 20 "" _null_ _null_ _null_ pg_stat_get_sort_index_all - _null_ )); + DESCR("Statistics: pg_stat_get_sort_index_all"); + DATA(insert OID = 1973 ( pg_stat_get_sort_datum_all PGNSP PGUID 12 f f t f s 0 20 "" _null_ _null_ _null_ pg_stat_get_sort_datum_all - _null_ )); + DESCR("Statistics: pg_stat_get_sort_datum_all"); + DATA(insert OID = 1974 ( pg_stat_get_sort_heap_tape PGNSP PGUID 12 f f t f s 0 20 "" _null_ _null_ _null_ pg_stat_get_sort_heap_tape - _null_ )); + DESCR("Statistics: pg_stat_get_sort_heap_tape"); + DATA(insert OID = 1975 ( pg_stat_get_sort_datum_tape PGNSP PGUID 12 f f t f s 0 20 "" _null_ _null_ _null_ pg_stat_get_sort_datum_tape - _null_ )); + DESCR("Statistics: pg_stat_get_sort_datum_tape"); + DATA(insert OID = 1976 ( pg_stat_get_max_sort_size PGNSP PGUID 12 f f t f s 0 20 "" _null_ _null_ _null_ pg_stat_get_max_sort_size - _null_ )); + DESCR("Statistics: pg_stat_get_prev_sort_size"); + DATA(insert OID = 1977 ( pg_stat_get_prev_sort_size PGNSP PGUID 12 f f t f s 0 20 "" _null_ _null_ _null_ pg_stat_get_prev_sort_size - _null_ )); + DESCR("Statistics: pg_stat_get_prev_sort_size"); + DATA(insert OID = 1946 ( encode PGNSP PGUID 12 f f t f i 2 25 "17 25" _null_ _null_ _null_ binary_encode - _null_ )); DESCR("Convert bytea value into some ascii-only text string"); DATA(insert OID = 1947 ( decode PGNSP PGUID 12 f f t f i 2 17 "25 25" _null_ _null_ _null_ binary_decode - _null_ )); diff -rc postgresql-8.1beta2.orig/src/include/pgstat.h postgresql-8.1beta2/src/include/pgstat.h *** postgresql-8.1beta2.orig/src/include/pgstat.h 2005-09-24 11:29:48.000000000 +0900 --- postgresql-8.1beta2/src/include/pgstat.h 2005-09-24 13:49:38.000000000 +0900 *************** *** 189,194 **** --- 189,203 ---- int m_nentries; int m_xact_commit; int m_xact_rollback; + + int m_sort_heap_all; + int m_sort_index_all; + int m_sort_datum_all; + int m_sort_heap_tape; + int m_sort_datum_tape; + + Size m_sort_max_used_size; + PgStat_TableEntry m_entry[PGSTAT_NUM_TABENTRIES]; } PgStat_MsgTabstat; *************** *** 276,281 **** --- 285,299 ---- PgStat_Counter n_xact_rollback; PgStat_Counter n_blocks_fetched; PgStat_Counter n_blocks_hit; + + PgStat_Counter n_sort_heap_all; + PgStat_Counter n_sort_index_all; + PgStat_Counter n_sort_datum_all; + PgStat_Counter n_sort_heap_tape; + PgStat_Counter n_sort_datum_tape; + + Size sort_max_used_size; + int destroy; TimestampTz last_autovac_time; } PgStat_StatDBEntry; *************** *** 492,495 **** --- 510,521 ---- extern PgStat_StatBeEntry *pgstat_fetch_stat_beentry(int beid); extern int pgstat_fetch_stat_numbackends(void); + + extern void pgstat_count_sort_heap_all(void); + extern void pgstat_count_sort_index_all(void); + extern void pgstat_count_sort_datum_all(void); + extern void pgstat_count_sort_heap_tape(void); + extern void pgstat_count_sort_datum_tape(void); + extern void pgstat_count_sort_max_used_size(Size size); + #endif /* PGSTAT_H */ diff -rc postgresql-8.1beta2.orig/src/include/utils/tuplesort.h postgresql-8.1beta2/src/include/utils/tuplesort.h *** postgresql-8.1beta2.orig/src/include/utils/tuplesort.h 2005-09-24 11:29:48.000000000 +0900 --- postgresql-8.1beta2/src/include/utils/tuplesort.h 2005-09-24 14:36:07.000000000 +0900 *************** *** 102,105 **** --- 102,107 ---- Datum datum1, bool isNull1, Datum datum2, bool isNull2); + extern Size tuplesort_get_prev_size(); + #endif /* TUPLESORT_H */