Skip to content

Commit 9cc2756

Browse files
committed
Fix pgstattuple's handling of unused hash pages.
Hash indexes can contain both pages which are all-zeroes (i.e. PageIsNew()) and pages which have been initialized but currently aren't used. The latter category can happen either when a page has been reserved but not yet used or when it is used for a time and then freed. pgstattuple was only prepared to deal with the pages that are actually-zeroes, which it called zero_pages. Rename the column to unused_pages (extension version 1.5 is as-yet-unreleased) and make it count both kinds of unused pages. Along the way, slightly tidy up the way we test for pages of various types. Robert Haas and Ashutosh Sharma, reviewed by Amit Kapila Discussion: http://postgr.es/m/CAE9k0PkTtKFB3YndOyQMjwuHx+-FtUP1ynK8E-nHtetoow3NtQ@mail.gmail.com
1 parent 1d5fede commit 9cc2756

File tree

4 files changed

+22
-16
lines changed

4 files changed

+22
-16
lines changed

contrib/pgstattuple/expected/pgstattuple.out

+3-3
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,9 @@ select * from pgstatginindex('test_ginidx');
132132

133133
create index test_hashidx on test using hash (b);
134134
select * from pgstathashindex('test_hashidx');
135-
version | bucket_pages | overflow_pages | bitmap_pages | zero_pages | live_items | dead_items | free_percent
136-
---------+--------------+----------------+--------------+------------+------------+------------+--------------
137-
3 | 4 | 0 | 1 | 0 | 0 | 0 | 100
135+
version | bucket_pages | overflow_pages | bitmap_pages | unused_pages | live_items | dead_items | free_percent
136+
---------+--------------+----------------+--------------+--------------+------------+------------+--------------
137+
3 | 4 | 0 | 1 | 0 | 0 | 0 | 100
138138
(1 row)
139139

140140
-- these should error with the wrong type

contrib/pgstattuple/pgstatindex.c

+15-9
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ typedef struct HashIndexStat
119119
BlockNumber bucket_pages;
120120
BlockNumber overflow_pages;
121121
BlockNumber bitmap_pages;
122-
BlockNumber zero_pages;
122+
BlockNumber unused_pages;
123123

124124
int64 live_items;
125125
int64 dead_items;
@@ -634,7 +634,6 @@ pgstathashindex(PG_FUNCTION_ARGS)
634634
{
635635
Buffer buf;
636636
Page page;
637-
HashPageOpaque opaque;
638637

639638
CHECK_FOR_INTERRUPTS();
640639

@@ -644,7 +643,7 @@ pgstathashindex(PG_FUNCTION_ARGS)
644643
page = (Page) BufferGetPage(buf);
645644

646645
if (PageIsNew(page))
647-
stats.zero_pages++;
646+
stats.unused_pages++;
648647
else if (PageGetSpecialSize(page) !=
649648
MAXALIGN(sizeof(HashPageOpaqueData)))
650649
ereport(ERROR,
@@ -654,19 +653,26 @@ pgstathashindex(PG_FUNCTION_ARGS)
654653
BufferGetBlockNumber(buf))));
655654
else
656655
{
656+
HashPageOpaque opaque;
657+
int pagetype;
658+
657659
opaque = (HashPageOpaque) PageGetSpecialPointer(page);
658-
if (opaque->hasho_flag & LH_BUCKET_PAGE)
660+
pagetype = opaque->hasho_flag & LH_PAGE_TYPE;
661+
662+
if (pagetype == LH_BUCKET_PAGE)
659663
{
660664
stats.bucket_pages++;
661665
GetHashPageStats(page, &stats);
662666
}
663-
else if (opaque->hasho_flag & LH_OVERFLOW_PAGE)
667+
else if (pagetype == LH_OVERFLOW_PAGE)
664668
{
665669
stats.overflow_pages++;
666670
GetHashPageStats(page, &stats);
667671
}
668-
else if (opaque->hasho_flag & LH_BITMAP_PAGE)
672+
else if (pagetype == LH_BITMAP_PAGE)
669673
stats.bitmap_pages++;
674+
else if (pagetype == LH_UNUSED_PAGE)
675+
stats.unused_pages++;
670676
else
671677
ereport(ERROR,
672678
(errcode(ERRCODE_INDEX_CORRUPTED),
@@ -680,8 +686,8 @@ pgstathashindex(PG_FUNCTION_ARGS)
680686
/* Done accessing the index */
681687
index_close(rel, AccessShareLock);
682688

683-
/* Count zero pages as free space. */
684-
stats.free_space += stats.zero_pages * stats.space_per_page;
689+
/* Count unused pages as free space. */
690+
stats.free_space += stats.unused_pages * stats.space_per_page;
685691

686692
/*
687693
* Total space available for tuples excludes the metapage and the bitmap
@@ -710,7 +716,7 @@ pgstathashindex(PG_FUNCTION_ARGS)
710716
values[1] = Int64GetDatum((int64) stats.bucket_pages);
711717
values[2] = Int64GetDatum((int64) stats.overflow_pages);
712718
values[3] = Int64GetDatum((int64) stats.bitmap_pages);
713-
values[4] = Int64GetDatum((int64) stats.zero_pages);
719+
values[4] = Int64GetDatum((int64) stats.unused_pages);
714720
values[5] = Int64GetDatum(stats.live_items);
715721
values[6] = Int64GetDatum(stats.dead_items);
716722
values[7] = Float8GetDatum(free_percent);

contrib/pgstattuple/pgstattuple--1.4--1.5.sql

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ CREATE OR REPLACE FUNCTION pgstathashindex(IN relname regclass,
125125
OUT bucket_pages BIGINT,
126126
OUT overflow_pages BIGINT,
127127
OUT bitmap_pages BIGINT,
128-
OUT zero_pages BIGINT,
128+
OUT unused_pages BIGINT,
129129
OUT live_items BIGINT,
130130
OUT dead_items BIGINT,
131131
OUT free_percent FLOAT8)

doc/src/sgml/pgstattuple.sgml

+3-3
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ version | 2
372372
bucket_pages | 33081
373373
overflow_pages | 0
374374
bitmap_pages | 1
375-
zero_pages | 32455
375+
unused_pages | 32455
376376
live_items | 10204006
377377
dead_items | 0
378378
free_percent | 61.8005949100872
@@ -418,9 +418,9 @@ free_percent | 61.8005949100872
418418
</row>
419419

420420
<row>
421-
<entry><structfield>zero_pages</structfield></entry>
421+
<entry><structfield>unused_pages</structfield></entry>
422422
<entry><type>bigint</type></entry>
423-
<entry>Number of new or zero pages</entry>
423+
<entry>Number of unused pages</entry>
424424
</row>
425425

426426
<row>

0 commit comments

Comments
 (0)