PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pgstatindex.c File Reference
#include "postgres.h"
#include "access/gin_private.h"
#include "access/hash.h"
#include "access/htup_details.h"
#include "access/nbtree.h"
#include "access/relation.h"
#include "catalog/namespace.h"
#include "catalog/pg_am.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "storage/bufmgr.h"
#include "storage/read_stream.h"
#include "utils/rel.h"
#include "utils/varlena.h"
Include dependency graph for pgstatindex.c:

Go to the source code of this file.

Data Structures

struct  BTIndexStat
 
struct  GinIndexStat
 
struct  HashIndexStat
 

Macros

#define IS_INDEX(r)   ((r)->rd_rel->relkind == RELKIND_INDEX)
 
#define IS_BTREE(r)   ((r)->rd_rel->relam == BTREE_AM_OID)
 
#define IS_GIN(r)   ((r)->rd_rel->relam == GIN_AM_OID)
 
#define IS_HASH(r)   ((r)->rd_rel->relam == HASH_AM_OID)
 

Typedefs

typedef struct BTIndexStat BTIndexStat
 
typedef struct GinIndexStat GinIndexStat
 
typedef struct HashIndexStat HashIndexStat
 

Functions

 PG_FUNCTION_INFO_V1 (pgstatindex)
 
 PG_FUNCTION_INFO_V1 (pgstatindexbyid)
 
 PG_FUNCTION_INFO_V1 (pg_relpages)
 
 PG_FUNCTION_INFO_V1 (pg_relpagesbyid)
 
 PG_FUNCTION_INFO_V1 (pgstatginindex)
 
 PG_FUNCTION_INFO_V1 (pgstathashindex)
 
 PG_FUNCTION_INFO_V1 (pgstatindex_v1_5)
 
 PG_FUNCTION_INFO_V1 (pgstatindexbyid_v1_5)
 
 PG_FUNCTION_INFO_V1 (pg_relpages_v1_5)
 
 PG_FUNCTION_INFO_V1 (pg_relpagesbyid_v1_5)
 
 PG_FUNCTION_INFO_V1 (pgstatginindex_v1_5)
 
Datum pgstatginindex_internal (Oid relid, FunctionCallInfo fcinfo)
 
static Datum pgstatindex_impl (Relation rel, FunctionCallInfo fcinfo)
 
static int64 pg_relpages_impl (Relation rel)
 
static void GetHashPageStats (Page page, HashIndexStat *stats)
 
Datum pgstatindex (PG_FUNCTION_ARGS)
 
Datum pgstatindex_v1_5 (PG_FUNCTION_ARGS)
 
Datum pgstatindexbyid (PG_FUNCTION_ARGS)
 
Datum pgstatindexbyid_v1_5 (PG_FUNCTION_ARGS)
 
Datum pg_relpages (PG_FUNCTION_ARGS)
 
Datum pg_relpages_v1_5 (PG_FUNCTION_ARGS)
 
Datum pg_relpagesbyid (PG_FUNCTION_ARGS)
 
Datum pg_relpagesbyid_v1_5 (PG_FUNCTION_ARGS)
 
Datum pgstatginindex (PG_FUNCTION_ARGS)
 
Datum pgstatginindex_v1_5 (PG_FUNCTION_ARGS)
 
Datum pgstathashindex (PG_FUNCTION_ARGS)
 

Macro Definition Documentation

◆ IS_BTREE

#define IS_BTREE (   r)    ((r)->rd_rel->relam == BTREE_AM_OID)

Definition at line 69 of file pgstatindex.c.

◆ IS_GIN

#define IS_GIN (   r)    ((r)->rd_rel->relam == GIN_AM_OID)

Definition at line 70 of file pgstatindex.c.

◆ IS_HASH

#define IS_HASH (   r)    ((r)->rd_rel->relam == HASH_AM_OID)

Definition at line 71 of file pgstatindex.c.

◆ IS_INDEX

#define IS_INDEX (   r)    ((r)->rd_rel->relkind == RELKIND_INDEX)

Definition at line 68 of file pgstatindex.c.

Typedef Documentation

◆ BTIndexStat

◆ GinIndexStat

◆ HashIndexStat

Function Documentation

◆ GetHashPageStats()

static void GetHashPageStats ( Page  page,
HashIndexStat stats 
)
static

Definition at line 794 of file pgstatindex.c.

795{
797 int off;
798
799 /* count live and dead tuples, and free space */
800 for (off = FirstOffsetNumber; off <= maxoff; off++)
801 {
802 ItemId id = PageGetItemId(page, off);
803
804 if (!ItemIdIsDead(id))
805 stats->live_items++;
806 else
807 stats->dead_items++;
808 }
809 stats->free_space += PageGetExactFreeSpace(page);
810}
Size PageGetExactFreeSpace(const PageData *page)
Definition bufpage.c:957
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
Definition bufpage.h:269
static OffsetNumber PageGetMaxOffsetNumber(const PageData *page)
Definition bufpage.h:397
#define ItemIdIsDead(itemId)
Definition itemid.h:113
uint16 OffsetNumber
Definition off.h:24
#define FirstOffsetNumber
Definition off.h:27
uint64 free_space

References HashIndexStat::dead_items, FirstOffsetNumber, HashIndexStat::free_space, ItemIdIsDead, HashIndexStat::live_items, PageGetExactFreeSpace(), PageGetItemId(), and PageGetMaxOffsetNumber().

Referenced by pgstathashindex().

◆ PG_FUNCTION_INFO_V1() [1/11]

PG_FUNCTION_INFO_V1 ( pg_relpages  )

◆ PG_FUNCTION_INFO_V1() [2/11]

PG_FUNCTION_INFO_V1 ( pg_relpages_v1_5  )

◆ PG_FUNCTION_INFO_V1() [3/11]

PG_FUNCTION_INFO_V1 ( pg_relpagesbyid  )

◆ PG_FUNCTION_INFO_V1() [4/11]

PG_FUNCTION_INFO_V1 ( pg_relpagesbyid_v1_5  )

◆ PG_FUNCTION_INFO_V1() [5/11]

PG_FUNCTION_INFO_V1 ( pgstatginindex  )

◆ PG_FUNCTION_INFO_V1() [6/11]

PG_FUNCTION_INFO_V1 ( pgstatginindex_v1_5  )

◆ PG_FUNCTION_INFO_V1() [7/11]

PG_FUNCTION_INFO_V1 ( pgstathashindex  )

◆ PG_FUNCTION_INFO_V1() [8/11]

PG_FUNCTION_INFO_V1 ( pgstatindex  )

◆ PG_FUNCTION_INFO_V1() [9/11]

PG_FUNCTION_INFO_V1 ( pgstatindex_v1_5  )

◆ PG_FUNCTION_INFO_V1() [10/11]

PG_FUNCTION_INFO_V1 ( pgstatindexbyid  )

◆ PG_FUNCTION_INFO_V1() [11/11]

PG_FUNCTION_INFO_V1 ( pgstatindexbyid_v1_5  )

◆ pg_relpages()

Datum pg_relpages ( PG_FUNCTION_ARGS  )

Definition at line 413 of file pgstatindex.c.

414{
416 Relation rel;
418
419 if (!superuser())
422 errmsg("must be superuser to use pgstattuple functions")));
423
426
428}
int errcode(int sqlerrcode)
Definition elog.c:874
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
#define PG_GETARG_TEXT_PP(n)
Definition fmgr.h:310
#define PG_RETURN_INT64(x)
Definition fmgr.h:370
#define AccessShareLock
Definition lockdefs.h:36
RangeVar * makeRangeVarFromNameList(const List *names)
Definition namespace.c:3626
static char * errmsg
NameData relname
Definition pg_class.h:40
static int64 pg_relpages_impl(Relation rel)
static int fb(int x)
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition relation.c:137
Definition c.h:760
bool superuser(void)
Definition superuser.c:47
List * textToQualifiedNameList(text *textval)
Definition varlena.c:2717

References AccessShareLock, ereport, errcode(), errmsg, ERROR, fb(), makeRangeVarFromNameList(), PG_GETARG_TEXT_PP, pg_relpages_impl(), PG_RETURN_INT64, relation_openrv(), relname, superuser(), and textToQualifiedNameList().

◆ pg_relpages_impl()

static int64 pg_relpages_impl ( Relation  rel)
static

Definition at line 474 of file pgstatindex.c.

475{
476 int64 relpages;
477
478 if (!RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
481 errmsg("cannot get page count of relation \"%s\"",
484
485 /* note: this will work OK on non-local temp tables */
486
487 relpages = RelationGetNumberOfBlocks(rel);
488
490
491 return relpages;
492}
#define RelationGetNumberOfBlocks(reln)
Definition bufmgr.h:307
int64_t int64
Definition c.h:597
int errdetail_relkind_not_supported(char relkind)
Definition pg_class.c:24
#define RelationGetRelationName(relation)
Definition rel.h:548
void relation_close(Relation relation, LOCKMODE lockmode)
Definition relation.c:205
Form_pg_class rd_rel
Definition rel.h:111

References AccessShareLock, ereport, errcode(), errdetail_relkind_not_supported(), errmsg, ERROR, fb(), RelationData::rd_rel, relation_close(), RelationGetNumberOfBlocks, and RelationGetRelationName.

Referenced by pg_relpages(), pg_relpages_v1_5(), pg_relpagesbyid(), and pg_relpagesbyid_v1_5().

◆ pg_relpages_v1_5()

◆ pg_relpagesbyid()

Datum pg_relpagesbyid ( PG_FUNCTION_ARGS  )

Definition at line 446 of file pgstatindex.c.

447{
448 Oid relid = PG_GETARG_OID(0);
449 Relation rel;
450
451 if (!superuser())
454 errmsg("must be superuser to use pgstattuple functions")));
455
456 rel = relation_open(relid, AccessShareLock);
457
459}
#define PG_GETARG_OID(n)
Definition fmgr.h:275
unsigned int Oid
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition relation.c:47

References AccessShareLock, ereport, errcode(), errmsg, ERROR, fb(), PG_GETARG_OID, pg_relpages_impl(), PG_RETURN_INT64, relation_open(), and superuser().

◆ pg_relpagesbyid_v1_5()

Datum pg_relpagesbyid_v1_5 ( PG_FUNCTION_ARGS  )

Definition at line 463 of file pgstatindex.c.

464{
465 Oid relid = PG_GETARG_OID(0);
466 Relation rel;
467
468 rel = relation_open(relid, AccessShareLock);
469
471}

References AccessShareLock, PG_GETARG_OID, pg_relpages_impl(), PG_RETURN_INT64, and relation_open().

◆ pgstatginindex()

Datum pgstatginindex ( PG_FUNCTION_ARGS  )

Definition at line 503 of file pgstatindex.c.

504{
505 Oid relid = PG_GETARG_OID(0);
506
507 if (!superuser())
510 errmsg("must be superuser to use pgstattuple functions")));
511
513}
#define PG_RETURN_DATUM(x)
Definition fmgr.h:354
Datum pgstatginindex_internal(Oid relid, FunctionCallInfo fcinfo)

References ereport, errcode(), errmsg, ERROR, fb(), PG_GETARG_OID, PG_RETURN_DATUM, pgstatginindex_internal(), and superuser().

◆ pgstatginindex_internal()

Datum pgstatginindex_internal ( Oid  relid,
FunctionCallInfo  fcinfo 
)

Definition at line 525 of file pgstatindex.c.

526{
527 Relation rel;
528 Buffer buffer;
529 Page page;
530 GinMetaPageData *metadata;
531 GinIndexStat stats;
532 HeapTuple tuple;
534 Datum values[3];
535 bool nulls[3] = {false, false, false};
536 Datum result;
537
538 /*
539 * This uses relation_open() and not index_open(). The latter allows
540 * partitioned indexes, and these are forbidden here.
541 */
542 rel = relation_open(relid, AccessShareLock);
543
544 if (!IS_INDEX(rel) || !IS_GIN(rel))
547 errmsg("relation \"%s\" is not a GIN index",
549
550 /*
551 * Reject attempts to read non-local temporary relations; we would be
552 * likely to get wrong data since we have no visibility into the owning
553 * session's local buffers.
554 */
555 if (RELATION_IS_OTHER_TEMP(rel))
558 errmsg("cannot access temporary indexes of other sessions")));
559
560 /* see pgstatindex_impl */
561 if (!rel->rd_index->indisvalid)
564 errmsg("index \"%s\" is not valid",
566
567 /*
568 * Read metapage
569 */
570 buffer = ReadBuffer(rel, GIN_METAPAGE_BLKNO);
571 LockBuffer(buffer, GIN_SHARE);
572 page = BufferGetPage(buffer);
573 metadata = GinPageGetMeta(page);
574
575 stats.version = metadata->ginVersion;
576 stats.pending_pages = metadata->nPendingPages;
577 stats.pending_tuples = metadata->nPendingHeapTuples;
578
579 UnlockReleaseBuffer(buffer);
581
582 /*
583 * Build a tuple descriptor for our result type
584 */
586 elog(ERROR, "return type must be a row type");
587
588 values[0] = Int32GetDatum(stats.version);
591
592 /*
593 * Build and return the tuple
594 */
595 tuple = heap_form_tuple(tupleDesc, values, nulls);
596 result = HeapTupleGetDatum(tuple);
597
598 return result;
599}
static Datum values[MAXATTR]
Definition bootstrap.c:187
int Buffer
Definition buf.h:23
void UnlockReleaseBuffer(Buffer buffer)
Definition bufmgr.c:5522
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition bufmgr.c:874
static Page BufferGetPage(Buffer buffer)
Definition bufmgr.h:470
static void LockBuffer(Buffer buffer, BufferLockMode mode)
Definition bufmgr.h:332
PageData * Page
Definition bufpage.h:81
#define elog(elevel,...)
Definition elog.h:226
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition funcapi.c:276
@ TYPEFUNC_COMPOSITE
Definition funcapi.h:149
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Definition funcapi.h:230
#define GIN_SHARE
Definition gin_private.h:51
#define GIN_METAPAGE_BLKNO
Definition ginblock.h:51
#define GinPageGetMeta(p)
Definition ginblock.h:104
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1117
#define IS_INDEX(r)
Definition pgstatindex.c:68
#define IS_GIN(r)
Definition pgstatindex.c:70
static Datum Int64GetDatum(int64 X)
Definition postgres.h:413
uint64_t Datum
Definition postgres.h:70
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
static Datum UInt32GetDatum(uint32 X)
Definition postgres.h:232
#define RELATION_IS_OTHER_TEMP(relation)
Definition rel.h:667
BlockNumber pending_pages
int64 pending_tuples
int32 ginVersion
Definition ginblock.h:99
BlockNumber nPendingPages
Definition ginblock.h:73
int64 nPendingHeapTuples
Definition ginblock.h:74
Form_pg_index rd_index
Definition rel.h:192

References AccessShareLock, BufferGetPage(), elog, ereport, errcode(), errmsg, ERROR, fb(), get_call_result_type(), GIN_METAPAGE_BLKNO, GIN_SHARE, GinPageGetMeta, GinMetaPageData::ginVersion, heap_form_tuple(), HeapTupleGetDatum(), Int32GetDatum(), Int64GetDatum(), IS_GIN, IS_INDEX, LockBuffer(), GinMetaPageData::nPendingHeapTuples, GinMetaPageData::nPendingPages, GinIndexStat::pending_pages, GinIndexStat::pending_tuples, RelationData::rd_index, ReadBuffer(), relation_close(), RELATION_IS_OTHER_TEMP, relation_open(), RelationGetRelationName, TYPEFUNC_COMPOSITE, UInt32GetDatum(), UnlockReleaseBuffer(), values, and GinIndexStat::version.

Referenced by pgstatginindex(), and pgstatginindex_v1_5().

◆ pgstatginindex_v1_5()

Datum pgstatginindex_v1_5 ( PG_FUNCTION_ARGS  )

Definition at line 517 of file pgstatindex.c.

518{
519 Oid relid = PG_GETARG_OID(0);
520
522}

References PG_GETARG_OID, PG_RETURN_DATUM, and pgstatginindex_internal().

◆ pgstathashindex()

Datum pgstathashindex ( PG_FUNCTION_ARGS  )

Definition at line 608 of file pgstatindex.c.

609{
610 Oid relid = PG_GETARG_OID(0);
611 BlockNumber nblocks;
612 BlockNumber blkno;
613 Relation rel;
614 HashIndexStat stats;
615 BufferAccessStrategy bstrategy;
616 HeapTuple tuple;
618 Datum values[8];
619 bool nulls[8] = {0};
622 float8 free_percent;
625 ReadStream *stream;
627
628 /*
629 * This uses relation_open() and not index_open(). The latter allows
630 * partitioned indexes, and these are forbidden here.
631 */
632 rel = relation_open(relid, AccessShareLock);
633
634 if (!IS_INDEX(rel) || !IS_HASH(rel))
637 errmsg("relation \"%s\" is not a hash index",
639
640 /*
641 * Reject attempts to read non-local temporary relations; we would be
642 * likely to get wrong data since we have no visibility into the owning
643 * session's local buffers.
644 */
645 if (RELATION_IS_OTHER_TEMP(rel))
648 errmsg("cannot access temporary indexes of other sessions")));
649
650 /* see pgstatindex_impl */
651 if (!rel->rd_index->indisvalid)
654 errmsg("index \"%s\" is not valid",
656
657 /* Get the information we need from the metapage. */
658 memset(&stats, 0, sizeof(stats));
661 stats.version = metap->hashm_version;
662 stats.space_per_page = metap->hashm_bsize;
663 _hash_relbuf(rel, metabuf);
664
665 /* Get the current relation length */
666 nblocks = RelationGetNumberOfBlocks(rel);
667
668 /* prepare access strategy for this index */
669 bstrategy = GetAccessStrategy(BAS_BULKREAD);
670
671 /* Scan all blocks except the metapage (0th page) using streaming reads */
673
675 p.last_exclusive = nblocks;
676
677 /*
678 * It is safe to use batchmode as block_range_read_stream_cb takes no
679 * locks.
680 */
683 bstrategy,
684 rel,
687 &p,
688 0);
689
690 for (blkno = startblk; blkno < nblocks; blkno++)
691 {
692 Buffer buf;
693 Page page;
694
696
699 page = BufferGetPage(buf);
700
701 if (PageIsNew(page))
702 stats.unused_pages++;
703 else if (PageGetSpecialSize(page) !=
707 errmsg("index \"%s\" contains corrupted page at block %u",
710 else
711 {
712 HashPageOpaque opaque;
713 int pagetype;
714
715 opaque = HashPageGetOpaque(page);
716 pagetype = opaque->hasho_flag & LH_PAGE_TYPE;
717
719 {
720 stats.bucket_pages++;
721 GetHashPageStats(page, &stats);
722 }
723 else if (pagetype == LH_OVERFLOW_PAGE)
724 {
725 stats.overflow_pages++;
726 GetHashPageStats(page, &stats);
727 }
728 else if (pagetype == LH_BITMAP_PAGE)
729 stats.bitmap_pages++;
730 else if (pagetype == LH_UNUSED_PAGE)
731 stats.unused_pages++;
732 else
735 errmsg("unexpected page type 0x%04X in HASH index \"%s\" block %u",
738 }
740 }
741
743 read_stream_end(stream);
744
745 /* Done accessing the index */
747
748 /* Count unused pages as free space. */
749 stats.free_space += (uint64) stats.unused_pages * stats.space_per_page;
750
751 /*
752 * Total space available for tuples excludes the metapage and the bitmap
753 * pages.
754 */
755 total_space = (uint64) (nblocks - (stats.bitmap_pages + 1)) *
756 stats.space_per_page;
757
758 if (total_space == 0)
759 free_percent = 0.0;
760 else
761 free_percent = 100.0 * stats.free_space / total_space;
762
763 /*
764 * Build a tuple descriptor for our result type
765 */
767 elog(ERROR, "return type must be a row type");
768
770
771 /*
772 * Build and return the tuple
773 */
774 values[0] = Int32GetDatum(stats.version);
779 values[5] = Int64GetDatum(stats.live_items);
780 values[6] = Int64GetDatum(stats.dead_items);
781 values[7] = Float8GetDatum(free_percent);
782 tuple = heap_form_tuple(tupleDesc, values, nulls);
783
785}
uint32 BlockNumber
Definition block.h:31
#define InvalidBuffer
Definition buf.h:25
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition bufmgr.c:4357
@ BAS_BULKREAD
Definition bufmgr.h:37
@ BUFFER_LOCK_SHARE
Definition bufmgr.h:210
static uint16 PageGetSpecialSize(const PageData *page)
Definition bufpage.h:342
static bool PageIsNew(const PageData *page)
Definition bufpage.h:259
#define MAXALIGN(LEN)
Definition c.h:880
#define Assert(condition)
Definition c.h:927
double float8
Definition c.h:698
uint64_t uint64
Definition c.h:601
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype)
Definition freelist.c:461
#define HashPageGetOpaque(page)
Definition hash.h:88
#define LH_BUCKET_PAGE
Definition hash.h:55
#define LH_UNUSED_PAGE
Definition hash.h:53
#define LH_META_PAGE
Definition hash.h:57
#define HashPageGetMeta(page)
Definition hash.h:323
#define HASH_READ
Definition hash.h:339
#define HASH_METAPAGE
Definition hash.h:198
#define LH_PAGE_TYPE
Definition hash.h:63
#define LH_BITMAP_PAGE
Definition hash.h:56
#define LH_OVERFLOW_PAGE
Definition hash.h:54
void _hash_relbuf(Relation rel, Buffer buf)
Definition hashpage.c:266
Buffer _hash_getbuf(Relation rel, BlockNumber blkno, int access, int flags)
Definition hashpage.c:70
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:123
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define IS_HASH(r)
Definition pgstatindex.c:71
static void GetHashPageStats(Page page, HashIndexStat *stats)
static Datum Float8GetDatum(float8 X)
Definition postgres.h:502
Buffer read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
ReadStream * read_stream_begin_relation(int flags, BufferAccessStrategy strategy, Relation rel, ForkNumber forknum, ReadStreamBlockNumberCB callback, void *callback_private_data, size_t per_buffer_data_size)
void read_stream_end(ReadStream *stream)
BlockNumber block_range_read_stream_cb(ReadStream *stream, void *callback_private_data, void *per_buffer_data)
#define READ_STREAM_USE_BATCHING
Definition read_stream.h:64
#define READ_STREAM_FULL
Definition read_stream.h:43
@ MAIN_FORKNUM
Definition relpath.h:58
BlockNumber bitmap_pages
BlockNumber overflow_pages
BlockNumber bucket_pages
BlockNumber unused_pages
int32 space_per_page
uint16 hasho_flag
Definition hash.h:82

References _hash_getbuf(), _hash_relbuf(), AccessShareLock, Assert, BAS_BULKREAD, HashIndexStat::bitmap_pages, BlessTupleDesc(), block_range_read_stream_cb(), HashIndexStat::bucket_pages, buf, BUFFER_LOCK_SHARE, BufferGetBlockNumber(), BufferGetPage(), CHECK_FOR_INTERRUPTS, BlockRangeReadStreamPrivate::current_blocknum, HashIndexStat::dead_items, elog, ereport, errcode(), errmsg, ERROR, fb(), Float8GetDatum(), HashIndexStat::free_space, get_call_result_type(), GetAccessStrategy(), GetHashPageStats(), HASH_METAPAGE, HASH_READ, HashPageOpaqueData::hasho_flag, HashPageGetMeta, HashPageGetOpaque, heap_form_tuple(), HeapTupleGetDatum(), Int32GetDatum(), Int64GetDatum(), InvalidBuffer, IS_HASH, IS_INDEX, BlockRangeReadStreamPrivate::last_exclusive, LH_BITMAP_PAGE, LH_BUCKET_PAGE, LH_META_PAGE, LH_OVERFLOW_PAGE, LH_PAGE_TYPE, LH_UNUSED_PAGE, HashIndexStat::live_items, LockBuffer(), MAIN_FORKNUM, MAXALIGN, HashIndexStat::overflow_pages, PageGetSpecialSize(), PageIsNew(), PG_GETARG_OID, PG_RETURN_DATUM, RelationData::rd_index, read_stream_begin_relation(), read_stream_end(), READ_STREAM_FULL, read_stream_next_buffer(), READ_STREAM_USE_BATCHING, relation_close(), RELATION_IS_OTHER_TEMP, relation_open(), RelationGetNumberOfBlocks, RelationGetRelationName, HashIndexStat::space_per_page, TYPEFUNC_COMPOSITE, UnlockReleaseBuffer(), HashIndexStat::unused_pages, values, and HashIndexStat::version.

◆ pgstatindex()

Datum pgstatindex ( PG_FUNCTION_ARGS  )

Definition at line 143 of file pgstatindex.c.

144{
146 Relation rel;
148
149 if (!superuser())
152 errmsg("must be superuser to use pgstattuple functions")));
153
156
157 PG_RETURN_DATUM(pgstatindex_impl(rel, fcinfo));
158}
static Datum pgstatindex_impl(Relation rel, FunctionCallInfo fcinfo)

References AccessShareLock, ereport, errcode(), errmsg, ERROR, fb(), makeRangeVarFromNameList(), PG_GETARG_TEXT_PP, PG_RETURN_DATUM, pgstatindex_impl(), relation_openrv(), relname, superuser(), and textToQualifiedNameList().

◆ pgstatindex_impl()

static Datum pgstatindex_impl ( Relation  rel,
FunctionCallInfo  fcinfo 
)
static

Definition at line 214 of file pgstatindex.c.

215{
216 Datum result;
217 BlockNumber nblocks;
218 BlockNumber blkno;
222 ReadStream *stream;
224
225 if (!IS_INDEX(rel) || !IS_BTREE(rel))
228 errmsg("relation \"%s\" is not a btree index",
230
231 /*
232 * Reject attempts to read non-local temporary relations; we would be
233 * likely to get wrong data since we have no visibility into the owning
234 * session's local buffers.
235 */
236 if (RELATION_IS_OTHER_TEMP(rel))
239 errmsg("cannot access temporary tables of other sessions")));
240
241 /*
242 * A !indisready index could lead to ERRCODE_DATA_CORRUPTED later, so exit
243 * early. We're capable of assessing an indisready&&!indisvalid index,
244 * but the results could be confusing. For example, the index's size
245 * could be too low for a valid index of the table.
246 */
247 if (!rel->rd_index->indisvalid)
250 errmsg("index \"%s\" is not valid",
252
253 /*
254 * Read metapage
255 */
256 {
257 Buffer buffer = ReadBufferExtended(rel, MAIN_FORKNUM, 0, RBM_NORMAL, bstrategy);
258 Page page = BufferGetPage(buffer);
260
261 indexStat.version = metad->btm_version;
262 indexStat.level = metad->btm_level;
263 indexStat.root_blkno = metad->btm_root;
264
265 ReleaseBuffer(buffer);
266 }
267
268 /* -- init counters -- */
269 indexStat.internal_pages = 0;
270 indexStat.leaf_pages = 0;
271 indexStat.empty_pages = 0;
272 indexStat.deleted_pages = 0;
273
274 indexStat.max_avail = 0;
275 indexStat.free_space = 0;
276
277 indexStat.fragments = 0;
278
279 /*
280 * Scan all blocks except the metapage (0th page) using streaming reads
281 */
282 nblocks = RelationGetNumberOfBlocks(rel);
284
286 p.last_exclusive = nblocks;
287
288 /*
289 * It is safe to use batchmode as block_range_read_stream_cb takes no
290 * locks.
291 */
294 bstrategy,
295 rel,
298 &p,
299 0);
300
301 for (blkno = startblk; blkno < nblocks; blkno++)
302 {
303 Buffer buffer;
304 Page page;
305 BTPageOpaque opaque;
306
308
309 buffer = read_stream_next_buffer(stream, NULL);
311
312 page = BufferGetPage(buffer);
313 opaque = BTPageGetOpaque(page);
314
315 /*
316 * Determine page type, and update totals.
317 *
318 * Note that we arbitrarily bucket deleted pages together without
319 * considering if they're leaf pages or internal pages.
320 */
321 if (P_ISDELETED(opaque))
322 indexStat.deleted_pages++;
323 else if (P_IGNORE(opaque))
324 indexStat.empty_pages++; /* this is the "half dead" state */
325 else if (P_ISLEAF(opaque))
326 {
327 int max_avail;
328
329 max_avail = BLCKSZ - (BLCKSZ - ((PageHeader) page)->pd_special + SizeOfPageHeaderData);
330 indexStat.max_avail += max_avail;
331 indexStat.free_space += PageGetExactFreeSpace(page);
332
333 indexStat.leaf_pages++;
334
335 /*
336 * If the next leaf is on an earlier block, it means a
337 * fragmentation.
338 */
339 if (opaque->btpo_next != P_NONE && opaque->btpo_next < blkno)
340 indexStat.fragments++;
341 }
342 else
343 indexStat.internal_pages++;
344
345 UnlockReleaseBuffer(buffer);
346 }
347
349 read_stream_end(stream);
350
352
353 /*----------------------------
354 * Build a result tuple
355 *----------------------------
356 */
357 {
359 int j;
360 char *values[10];
361 HeapTuple tuple;
362
363 /* Build a tuple descriptor for our result type */
365 elog(ERROR, "return type must be a row type");
366
367 j = 0;
368 values[j++] = psprintf("%d", indexStat.version);
369 values[j++] = psprintf("%d", indexStat.level);
371 (1 + /* include the metapage in index_size */
372 indexStat.leaf_pages +
373 indexStat.internal_pages +
374 indexStat.deleted_pages +
375 indexStat.empty_pages) * BLCKSZ);
376 values[j++] = psprintf("%u", indexStat.root_blkno);
377 values[j++] = psprintf(INT64_FORMAT, indexStat.internal_pages);
378 values[j++] = psprintf(INT64_FORMAT, indexStat.leaf_pages);
379 values[j++] = psprintf(INT64_FORMAT, indexStat.empty_pages);
380 values[j++] = psprintf(INT64_FORMAT, indexStat.deleted_pages);
381 if (indexStat.max_avail > 0)
382 values[j++] = psprintf("%.2f",
383 100.0 - (double) indexStat.free_space / (double) indexStat.max_avail * 100.0);
384 else
385 values[j++] = pstrdup("NaN");
386 if (indexStat.leaf_pages > 0)
387 values[j++] = psprintf("%.2f",
388 (double) indexStat.fragments / (double) indexStat.leaf_pages * 100.0);
389 else
390 values[j++] = pstrdup("NaN");
391
393 values);
394
395 result = HeapTupleGetDatum(tuple);
396 }
397
398 return result;
399}
void ReleaseBuffer(Buffer buffer)
Definition bufmgr.c:5505
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition bufmgr.c:921
@ RBM_NORMAL
Definition bufmgr.h:46
PageHeaderData * PageHeader
Definition bufpage.h:199
#define SizeOfPageHeaderData
Definition bufpage.h:242
#define INT64_FORMAT
Definition c.h:618
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)
int j
Definition isn.c:78
char * pstrdup(const char *in)
Definition mcxt.c:1781
#define BTPageGetMeta(p)
Definition nbtree.h:122
#define P_ISLEAF(opaque)
Definition nbtree.h:221
#define BTPageGetOpaque(page)
Definition nbtree.h:74
#define P_ISDELETED(opaque)
Definition nbtree.h:223
#define P_NONE
Definition nbtree.h:213
#define BTREE_METAPAGE
Definition nbtree.h:149
#define P_IGNORE(opaque)
Definition nbtree.h:226
#define IS_BTREE(r)
Definition pgstatindex.c:69
char * psprintf(const char *fmt,...)
Definition psprintf.c:43
BlockNumber btpo_next
Definition nbtree.h:66

References AccessShareLock, Assert, BAS_BULKREAD, block_range_read_stream_cb(), BTPageGetMeta, BTPageGetOpaque, BTPageOpaqueData::btpo_next, BTREE_METAPAGE, BUFFER_LOCK_SHARE, BufferGetPage(), BuildTupleFromCStrings(), CHECK_FOR_INTERRUPTS, BlockRangeReadStreamPrivate::current_blocknum, elog, ereport, errcode(), errmsg, ERROR, fb(), get_call_result_type(), GetAccessStrategy(), HeapTupleGetDatum(), INT64_FORMAT, InvalidBuffer, IS_BTREE, IS_INDEX, j, BlockRangeReadStreamPrivate::last_exclusive, LockBuffer(), MAIN_FORKNUM, P_IGNORE, P_ISDELETED, P_ISLEAF, P_NONE, PageGetExactFreeSpace(), psprintf(), pstrdup(), RBM_NORMAL, RelationData::rd_index, read_stream_begin_relation(), read_stream_end(), READ_STREAM_FULL, read_stream_next_buffer(), READ_STREAM_USE_BATCHING, ReadBufferExtended(), relation_close(), RELATION_IS_OTHER_TEMP, RelationGetNumberOfBlocks, RelationGetRelationName, ReleaseBuffer(), SizeOfPageHeaderData, TupleDescGetAttInMetadata(), TYPEFUNC_COMPOSITE, UnlockReleaseBuffer(), and values.

Referenced by pgstatindex(), pgstatindex_v1_5(), pgstatindexbyid(), and pgstatindexbyid_v1_5().

◆ pgstatindex_v1_5()

◆ pgstatindexbyid()

Datum pgstatindexbyid ( PG_FUNCTION_ARGS  )

Definition at line 186 of file pgstatindex.c.

187{
188 Oid relid = PG_GETARG_OID(0);
189 Relation rel;
190
191 if (!superuser())
194 errmsg("must be superuser to use pgstattuple functions")));
195
196 rel = relation_open(relid, AccessShareLock);
197
198 PG_RETURN_DATUM(pgstatindex_impl(rel, fcinfo));
199}

References AccessShareLock, ereport, errcode(), errmsg, ERROR, fb(), PG_GETARG_OID, PG_RETURN_DATUM, pgstatindex_impl(), relation_open(), and superuser().

◆ pgstatindexbyid_v1_5()

Datum pgstatindexbyid_v1_5 ( PG_FUNCTION_ARGS  )

Definition at line 203 of file pgstatindex.c.

204{
205 Oid relid = PG_GETARG_OID(0);
206 Relation rel;
207
208 rel = relation_open(relid, AccessShareLock);
209
210 PG_RETURN_DATUM(pgstatindex_impl(rel, fcinfo));
211}

References AccessShareLock, PG_GETARG_OID, PG_RETURN_DATUM, pgstatindex_impl(), and relation_open().