From cf7ee638a742474f92d40c0d6f1326bb8b06506e Mon Sep 17 00:00:00 2001 From: Tatsuo Ishii Date: Fri, 23 Aug 2002 08:19:49 +0000 Subject: [PATCH] Adapt for SRF(Set Returning Function). --- contrib/pgstattuple/README.pgstattuple | 54 ++++--- contrib/pgstattuple/README.pgstattuple.euc_jp | 59 +++++--- contrib/pgstattuple/pgstattuple.c | 138 +++++++++++++----- contrib/pgstattuple/pgstattuple.sql.in | 20 ++- 4 files changed, 189 insertions(+), 82 deletions(-) diff --git a/contrib/pgstattuple/README.pgstattuple b/contrib/pgstattuple/README.pgstattuple index 7237b9a4dc..804c37c6a9 100644 --- a/contrib/pgstattuple/README.pgstattuple +++ b/contrib/pgstattuple/README.pgstattuple @@ -1,27 +1,36 @@ -pgstattuple README 2001/10/01 Tatsuo Ishii +pgstattuple README 2002/08/22 Tatsuo Ishii 1. What is pgstattuple? - pgstattuple returns the percentage of the "dead" tuples of a - table. This will help users to judge if vacuum is needed. + pgstattuple returns the table length, percentage of the "dead" + tuples of a table and other info. This may help users to determine + whether vacuum is necessary or not. Here is an example session: - In addition, pgstattuple prints more detailed information using - NOTICE. +test=# \x +Expanded display is on. +test=# select * from pgstattuple('pg_proc'); +-[ RECORD 1 ]------+------- +table_len | 458752 +tuple_count | 1470 +tuple_len | 438896 +tuple_percent | 95.67 +dead_tuple_count | 11 +dead_tuple_len | 3157 +dead_tuple_percent | 0.69 +free_space | 8932 +free_percent | 1.95 -test=# select pgstattuple('tellers'); -NOTICE: physical length: 0.08MB live tuples: 20 (0.00MB, 1.17%) dead tuples: 320 (0.01MB, 18.75%) free/reusable space: 0.01MB (18.06%) overhead: 62.02% - pgstattuple -------------- - 18.75 -(1 row) - Above example shows tellers table includes 18.75% dead tuples. +Here are explanations for each column: - physical length physical size of the table in MB - live tuples information on the live tuples - dead tuples information on the dead tuples - free/reusable space available space - overhead overhead space +table_len -- physical table length in bytes +tuple_count -- number of live tuples +tuple_len -- total tuples length in bytes +tuple_percent -- live tuples in % +dead_tuple_len -- total dead tuples length in bytes +dead_tuple_percent -- dead tuples in % +free_space -- free space in bytes +free_percent -- free space in % 2. Installing pgstattuple @@ -31,12 +40,15 @@ NOTICE: physical length: 0.08MB live tuples: 20 (0.00MB, 1.17%) dead tuples: 32 3. Using pgstattuple - pgstattuple can be called as a function: + pgstattuple may be called as a SRF (set returning function) and is + defined as follows: - pgstattuple(TEXT) RETURNS FLOAT8 + CREATE OR REPLACE FUNCTION pgstattuple(text) RETURNS SETOF pgstattuple_view + AS 'MODULE_PATHNAME', 'pgstattuple' + LANGUAGE 'c' WITH (isstrict); - The argument is the table name. pgstattuple returns the percentage - of the "dead" tuples of a table. + The argument is the table name. Note that pgstattuple never + returns more than 1 tuple. 4. Notes diff --git a/contrib/pgstattuple/README.pgstattuple.euc_jp b/contrib/pgstattuple/README.pgstattuple.euc_jp index 5142e9b6a9..00a4bcbc74 100644 --- a/contrib/pgstattuple/README.pgstattuple.euc_jp +++ b/contrib/pgstattuple/README.pgstattuple.euc_jp @@ -1,34 +1,39 @@ -$Id: README.pgstattuple.euc_jp,v 1.2 2001/12/20 01:56:08 ishii Exp $ +$Id: README.pgstattuple.euc_jp,v 1.3 2002/08/23 08:19:49 ishii Exp $ -pgstattuple README 2001/10/01 石井達夫 +pgstattuple README 2002/08/22 石井達夫 1. pgstattupleとは pgstattupleは,UPDATEやDELETEで作られたテーブルのゴミ領域の大きさを, テーブル自体の物理的な大きさに対するパーセンテージで返却します.つ まり,返却値が大きければ,それだけゴミも多いので,vacuumをかける必 - 要があるという判断の助けになるわけです. + 要があるという判断の助けになるわけです.これ以外にもいろいろな情報 + が返ります. - これだけでは情報量が少ないので,NOTICEメッセージでいろんな情報をつ - いでに出力します. +test=# \x +Expanded display is on. +test=# select * from pgstattuple('pg_proc'); +-[ RECORD 1 ]------+------- +table_len | 458752 +tuple_count | 1470 +tuple_len | 438896 +tuple_percent | 95.67 +dead_tuple_count | 11 +dead_tuple_len | 3157 +dead_tuple_percent | 0.69 +free_space | 8932 +free_percent | 1.95 -test=# select pgstattuple('tellers'); -NOTICE: physical length: 0.08MB live tuples: 20 (0.00MB, 1.17%) dead tuples: 320 (0.01MB, 18.75%) free/reusable space: 0.01MB (18.06%) overhead: 62.02% - pgstattuple -------------- - 18.75 -(1 row) +各項目の説明です. - この実行例では,19%ほどがゴミになっていることが伺えます.NOTICEメッ - セージの見方も書いておきます. - - physical length テーブルの物理的なサイズをMB単位で表示 - live tuples ゴミではないタプルに関する情報.タプル数,各 - タプルが占める領域の合計,テーブル全体に対する - 比率を表示します. - dead tuples ゴミになったタプルに関する情報. - free/reusable space 利用可能な未使用領域や再利用可能領域 - overhead 管理のための領域がテーブル全体に占める比率 +table_len -- テーブルの物理的な大きさ(バイト) +tuple_count -- タプル数 +tuple_len -- タプル長の合計(バイト) +tuple_percent -- タプルの割合.table_lenに対するtuple_lenの比率. +dead_tuple_len -- デッドタプル数 +dead_tuple_percent -- デッドタプルの割合.table_lenに対するtuple_lenの比率. +free_space -- 再利用可能な領域(バイト) +free_percent -- 再利用可能な領域.table_lenに対するfree_spaceの比率. 2. pgstattupleのインストール @@ -47,12 +52,14 @@ NOTICE: physical length: 0.08MB live tuples: 20 (0.00MB, 1.17%) dead tuples: 32 pgstattupleの呼び出し形式は以下です. - pgstattuple(NAME) RETURNS FLOAT8 + CREATE OR REPLACE FUNCTION pgstattuple(text) RETURNS SETOF pgstattuple_view + AS 'MODULE_PATHNAME', 'pgstattuple' + LANGUAGE 'c' WITH (isstrict); 第一引数: テーブル名 - 関数の戻りはUPDATEやDELETEで作られたテーブルのゴミ領域の大きさで, - テーブルの物理的な大きさに対する割合(パーセント)で返却します. + 関数の戻りはpgstattuple_view型です.また,pgstattupleは1行しか行を + 返しません. なお,pgstattupleはテーブルにAccessShareLockしかかけないので, pgstattuple を実行中に該当テーブルに更新や削除が発生すると,正しく @@ -69,6 +76,10 @@ NOTICE: physical length: 0.08MB live tuples: 20 (0.00MB, 1.17%) dead tuples: 32 5. 改訂履歴 + 2002/08/23 + + SRF(Set Returning Function)を使って7.3用に書き換え. + 2001/12/20 Tom Laneによる修正 Fix pgstattuple to acquire a read lock on the target table. This diff --git a/contrib/pgstattuple/pgstattuple.c b/contrib/pgstattuple/pgstattuple.c index 498f820952..a357f6f412 100644 --- a/contrib/pgstattuple/pgstattuple.c +++ b/contrib/pgstattuple/pgstattuple.c @@ -1,7 +1,7 @@ /* - * $Header: /cvsroot/pgsql/contrib/pgstattuple/pgstattuple.c,v 1.6 2002/05/20 23:51:40 tgl Exp $ + * $Header: /cvsroot/pgsql/contrib/pgstattuple/pgstattuple.c,v 1.7 2002/08/23 08:19:49 ishii Exp $ * - * Copyright (c) 2001 Tatsuo Ishii + * Copyright (c) 2001,2002 Tatsuo Ishii * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose, without fee, and without a @@ -28,6 +28,7 @@ #include "access/heapam.h" #include "access/transam.h" #include "catalog/namespace.h" +#include "funcapi.h" #include "utils/builtins.h" @@ -37,16 +38,22 @@ extern Datum pgstattuple(PG_FUNCTION_ARGS); /* ---------- * pgstattuple: - * returns the percentage of dead tuples + * returns live/dead tuples info * * C FUNCTION definition - * pgstattuple(NAME) returns FLOAT8 + * pgstattuple(TEXT) returns setof pgstattuple_view + * see pgstattuple.sql for pgstattuple_view * ---------- */ + +#define DUMMY_TUPLE "pgstattuple_view" +#define NCOLUMNS 9 +#define NCHARS 32 + Datum pgstattuple(PG_FUNCTION_ARGS) { - text *relname = PG_GETARG_TEXT_P(0); + text *relname; RangeVar *relrv; Relation rel; HeapScanDesc scan; @@ -55,7 +62,7 @@ pgstattuple(PG_FUNCTION_ARGS) BlockNumber block = 0; /* next block to count free space in */ BlockNumber tupblock; Buffer buffer; - double table_len; + uint64 table_len; uint64 tuple_len = 0; uint64 dead_tuple_len = 0; uint64 tuple_count = 0; @@ -65,13 +72,67 @@ pgstattuple(PG_FUNCTION_ARGS) uint64 free_space = 0; /* free/reusable space in bytes */ double free_percent; /* free/reusable space in % */ - relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname, - "pgstattuple")); + FuncCallContext *funcctx; + int call_cntr; + int max_calls; + TupleDesc tupdesc; + TupleTableSlot *slot; + AttInMetadata *attinmeta; + + char **values; + int i; + Datum result; + + /* stuff done only on the first call of the function */ + if(SRF_IS_FIRSTCALL()) + { + /* create a function context for cross-call persistence */ + funcctx = SRF_FIRSTCALL_INIT(); + + /* total number of tuples to be returned */ + funcctx->max_calls = 1; + + /* + * Build a tuple description for a pgstattupe_view tuple + */ + tupdesc = RelationNameGetTupleDesc(DUMMY_TUPLE); + + /* allocate a slot for a tuple with this tupdesc */ + slot = TupleDescGetSlot(tupdesc); + + /* assign slot to function context */ + funcctx->slot = slot; + + /* + * Generate attribute metadata needed later to produce tuples from raw + * C strings + */ + attinmeta = TupleDescGetAttInMetadata(tupdesc); + funcctx->attinmeta = attinmeta; + } + + /* stuff done on every call of the function */ + funcctx = SRF_PERCALL_SETUP(); + call_cntr = funcctx->call_cntr; + max_calls = funcctx->max_calls; + slot = funcctx->slot; + attinmeta = funcctx->attinmeta; + + /* Are we done? */ + if (call_cntr >= max_calls) + { + SRF_RETURN_DONE(funcctx); + } + + /* open relation */ + relname = PG_GETARG_TEXT_P(0); + relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname,"pgstattuple")); rel = heap_openrv(relrv, AccessShareLock); nblocks = RelationGetNumberOfBlocks(rel); scan = heap_beginscan(rel, SnapshotAny, 0, NULL); + /* scan the relation */ while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) { if (HeapTupleSatisfiesNow(tuple->t_data)) @@ -113,7 +174,7 @@ pgstattuple(PG_FUNCTION_ARGS) heap_close(rel, AccessShareLock); - table_len = (double) nblocks *BLCKSZ; + table_len = (uint64)nblocks *BLCKSZ; if (nblocks == 0) { @@ -128,28 +189,39 @@ pgstattuple(PG_FUNCTION_ARGS) free_percent = (double) free_space *100.0 / table_len; } - elog(DEBUG3, "physical length: %.2fMB live tuples: %.0f (%.2fMB, %.2f%%) dead tuples: %.0f (%.2fMB, %.2f%%) free/reusable space: %.2fMB (%.2f%%) overhead: %.2f%%", - - table_len / (1024 * 1024), /* physical length in MB */ - - (double) tuple_count, /* number of live tuples */ - (double) tuple_len / (1024 * 1024), /* live tuples in MB */ - tuple_percent, /* live tuples in % */ - - (double) dead_tuple_count, /* number of dead tuples */ - (double) dead_tuple_len / (1024 * 1024), /* dead tuples in MB */ - dead_tuple_percent, /* dead tuples in % */ - - (double) free_space / (1024 * 1024), /* free/available space in - * MB */ - - free_percent, /* free/available space in % */ - - /* overhead in % */ - (nblocks == 0) ? 0.0 : 100.0 - - tuple_percent - - dead_tuple_percent - - free_percent); - - PG_RETURN_FLOAT8(dead_tuple_percent); + /* + * Prepare a values array for storage in our slot. + * This should be an array of C strings which will + * be processed later by the appropriate "in" functions. + */ + values = (char **) palloc(NCOLUMNS * sizeof(char *)); + for (i=0;i