Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit554106b

Browse files
committed
tableam: Provide helper functions for relation sizing.
Most block-based table AMs will need the exact same implementation ofthe relation_size callback as the heap, and if they use a standardpage layout, they will likely need an implementation of therelation_estimate_size callback that is very similar to that of theheap. Rearrange to facilitate code reuse.Patch by me, reviewed by Michael Paquier, Daniel Gustafsson, andÁlvaro Herrera.Discussion:http://postgr.es/m/CA+TgmoZ6DBPnP1E-vRpQZUJQijJFD54F+SR_pxGiAAS-MyrigA@mail.gmail.com
1 parent482501d commit554106b

File tree

3 files changed

+185
-119
lines changed

3 files changed

+185
-119
lines changed

‎src/backend/access/heap/heapam_handler.c

Lines changed: 10 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919
*/
2020
#include"postgres.h"
2121

22-
#include<math.h>
23-
2422
#include"miscadmin.h"
2523

2624
#include"access/genam.h"
@@ -37,7 +35,6 @@
3735
#include"catalog/storage_xlog.h"
3836
#include"commands/progress.h"
3937
#include"executor/executor.h"
40-
#include"optimizer/plancat.h"
4138
#include"pgstat.h"
4239
#include"storage/bufmgr.h"
4340
#include"storage/bufpage.h"
@@ -1991,26 +1988,6 @@ heapam_scan_get_blocks_done(HeapScanDesc hscan)
19911988
* ------------------------------------------------------------------------
19921989
*/
19931990

1994-
staticuint64
1995-
heapam_relation_size(Relationrel,ForkNumberforkNumber)
1996-
{
1997-
uint64nblocks=0;
1998-
1999-
/* Open it at the smgr level if not already done */
2000-
RelationOpenSmgr(rel);
2001-
2002-
/* InvalidForkNumber indicates returning the size for all forks */
2003-
if (forkNumber==InvalidForkNumber)
2004-
{
2005-
for (inti=0;i<MAX_FORKNUM;i++)
2006-
nblocks+=smgrnblocks(rel->rd_smgr,i);
2007-
}
2008-
else
2009-
nblocks=smgrnblocks(rel->rd_smgr,forkNumber);
2010-
2011-
returnnblocks*BLCKSZ;
2012-
}
2013-
20141991
/*
20151992
* Check to see whether the table needs a TOAST table. It does only if
20161993
* (1) there are any toastable attributes, and (2) the maximum length
@@ -2068,106 +2045,20 @@ heapam_relation_needs_toast_table(Relation rel)
20682045
* ------------------------------------------------------------------------
20692046
*/
20702047

2048+
#defineHEAP_OVERHEAD_BYTES_PER_TUPLE \
2049+
(MAXALIGN(SizeofHeapTupleHeader) + sizeof(ItemIdData))
2050+
#defineHEAP_USABLE_BYTES_PER_PAGE \
2051+
(BLCKSZ - SizeOfPageHeaderData)
2052+
20712053
staticvoid
20722054
heapam_estimate_rel_size(Relationrel,int32*attr_widths,
20732055
BlockNumber*pages,double*tuples,
20742056
double*allvisfrac)
20752057
{
2076-
BlockNumbercurpages;
2077-
BlockNumberrelpages;
2078-
doublereltuples;
2079-
BlockNumberrelallvisible;
2080-
doubledensity;
2081-
2082-
/* it has storage, ok to call the smgr */
2083-
curpages=RelationGetNumberOfBlocks(rel);
2084-
2085-
/* coerce values in pg_class to more desirable types */
2086-
relpages= (BlockNumber)rel->rd_rel->relpages;
2087-
reltuples= (double)rel->rd_rel->reltuples;
2088-
relallvisible= (BlockNumber)rel->rd_rel->relallvisible;
2089-
2090-
/*
2091-
* HACK: if the relation has never yet been vacuumed, use a minimum size
2092-
* estimate of 10 pages. The idea here is to avoid assuming a
2093-
* newly-created table is really small, even if it currently is, because
2094-
* that may not be true once some data gets loaded into it. Once a vacuum
2095-
* or analyze cycle has been done on it, it's more reasonable to believe
2096-
* the size is somewhat stable.
2097-
*
2098-
* (Note that this is only an issue if the plan gets cached and used again
2099-
* after the table has been filled. What we're trying to avoid is using a
2100-
* nestloop-type plan on a table that has grown substantially since the
2101-
* plan was made. Normally, autovacuum/autoanalyze will occur once enough
2102-
* inserts have happened and cause cached-plan invalidation; but that
2103-
* doesn't happen instantaneously, and it won't happen at all for cases
2104-
* such as temporary tables.)
2105-
*
2106-
* We approximate "never vacuumed" by "has relpages = 0", which means this
2107-
* will also fire on genuinely empty relations. Not great, but
2108-
* fortunately that's a seldom-seen case in the real world, and it
2109-
* shouldn't degrade the quality of the plan too much anyway to err in
2110-
* this direction.
2111-
*
2112-
* If the table has inheritance children, we don't apply this heuristic.
2113-
* Totally empty parent tables are quite common, so we should be willing
2114-
* to believe that they are empty.
2115-
*/
2116-
if (curpages<10&&
2117-
relpages==0&&
2118-
!rel->rd_rel->relhassubclass)
2119-
curpages=10;
2120-
2121-
/* report estimated # pages */
2122-
*pages=curpages;
2123-
/* quick exit if rel is clearly empty */
2124-
if (curpages==0)
2125-
{
2126-
*tuples=0;
2127-
*allvisfrac=0;
2128-
return;
2129-
}
2130-
2131-
/* estimate number of tuples from previous tuple density */
2132-
if (relpages>0)
2133-
density=reltuples / (double)relpages;
2134-
else
2135-
{
2136-
/*
2137-
* When we have no data because the relation was truncated, estimate
2138-
* tuple width from attribute datatypes. We assume here that the
2139-
* pages are completely full, which is OK for tables (since they've
2140-
* presumably not been VACUUMed yet) but is probably an overestimate
2141-
* for indexes. Fortunately get_relation_info() can clamp the
2142-
* overestimate to the parent table's size.
2143-
*
2144-
* Note: this code intentionally disregards alignment considerations,
2145-
* because (a) that would be gilding the lily considering how crude
2146-
* the estimate is, and (b) it creates platform dependencies in the
2147-
* default plans which are kind of a headache for regression testing.
2148-
*/
2149-
int32tuple_width;
2150-
2151-
tuple_width=get_rel_data_width(rel,attr_widths);
2152-
tuple_width+=MAXALIGN(SizeofHeapTupleHeader);
2153-
tuple_width+=sizeof(ItemIdData);
2154-
/* note: integer division is intentional here */
2155-
density= (BLCKSZ-SizeOfPageHeaderData) /tuple_width;
2156-
}
2157-
*tuples=rint(density* (double)curpages);
2158-
2159-
/*
2160-
* We use relallvisible as-is, rather than scaling it up like we do for
2161-
* the pages and tuples counts, on the theory that any pages added since
2162-
* the last VACUUM are most likely not marked all-visible. But costsize.c
2163-
* wants it converted to a fraction.
2164-
*/
2165-
if (relallvisible==0||curpages <=0)
2166-
*allvisfrac=0;
2167-
elseif ((double)relallvisible >=curpages)
2168-
*allvisfrac=1;
2169-
else
2170-
*allvisfrac= (double)relallvisible /curpages;
2058+
table_block_relation_estimate_size(rel,attr_widths,pages,
2059+
tuples,allvisfrac,
2060+
HEAP_OVERHEAD_BYTES_PER_TUPLE,
2061+
HEAP_USABLE_BYTES_PER_PAGE);
21712062
}
21722063

21732064

@@ -2644,7 +2535,7 @@ static const TableAmRoutine heapam_methods = {
26442535
.index_build_range_scan=heapam_index_build_range_scan,
26452536
.index_validate_scan=heapam_index_validate_scan,
26462537

2647-
.relation_size=heapam_relation_size,
2538+
.relation_size=table_block_relation_size,
26482539
.relation_needs_toast_table=heapam_relation_needs_toast_table,
26492540

26502541
.relation_estimate_size=heapam_estimate_rel_size,

‎src/backend/access/table/tableam.c

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,15 @@
1919
*/
2020
#include"postgres.h"
2121

22+
#include<math.h>
23+
2224
#include"access/heapam.h"/* for ss_* */
2325
#include"access/tableam.h"
2426
#include"access/xact.h"
27+
#include"optimizer/plancat.h"
2528
#include"storage/bufmgr.h"
2629
#include"storage/shmem.h"
30+
#include"storage/smgr.h"
2731

2832

2933
/* GUC variables */
@@ -486,3 +490,160 @@ table_block_parallelscan_nextpage(Relation rel, ParallelBlockTableScanDesc pbsca
486490

487491
returnpage;
488492
}
493+
494+
/* ----------------------------------------------------------------------------
495+
* Helper functions to implement relation sizing for block oriented AMs.
496+
* ----------------------------------------------------------------------------
497+
*/
498+
499+
/*
500+
* table_block_relation_size
501+
*
502+
* If a table AM uses the various relation forks as the sole place where data
503+
* is stored, and if it uses them in the expected manner (e.g. the actual data
504+
* is in the main fork rather than some other), it can use this implementation
505+
* of the relation_size callback rather than implementing its own.
506+
*/
507+
uint64
508+
table_block_relation_size(Relationrel,ForkNumberforkNumber)
509+
{
510+
uint64nblocks=0;
511+
512+
/* Open it at the smgr level if not already done */
513+
RelationOpenSmgr(rel);
514+
515+
/* InvalidForkNumber indicates returning the size for all forks */
516+
if (forkNumber==InvalidForkNumber)
517+
{
518+
for (inti=0;i<MAX_FORKNUM;i++)
519+
nblocks+=smgrnblocks(rel->rd_smgr,i);
520+
}
521+
else
522+
nblocks=smgrnblocks(rel->rd_smgr,forkNumber);
523+
524+
returnnblocks*BLCKSZ;
525+
}
526+
527+
/*
528+
* table_block_relation_estimate_size
529+
*
530+
* This function can't be directly used as the implementation of the
531+
* relation_estimate_size callback, because it has a few additional parameters.
532+
* Instead, it is intended to be used as a helper function; the caller can
533+
* pass through the arguments to its relation_estimate_size function plus the
534+
* additional values required here.
535+
*
536+
* overhead_bytes_per_tuple should contain the approximate number of bytes
537+
* of storage required to store a tuple above and beyond what is required for
538+
* the tuple data proper. Typically, this would include things like the
539+
* size of the tuple header and item pointer. This is only used for query
540+
* planning, so a table AM where the value is not constant could choose to
541+
* pass a "best guess".
542+
*
543+
* usable_bytes_per_page should contain the approximate number of bytes per
544+
* page usable for tuple data, excluding the page header and any anticipated
545+
* special space.
546+
*/
547+
void
548+
table_block_relation_estimate_size(Relationrel,int32*attr_widths,
549+
BlockNumber*pages,double*tuples,
550+
double*allvisfrac,
551+
Sizeoverhead_bytes_per_tuple,
552+
Sizeusable_bytes_per_page)
553+
{
554+
BlockNumbercurpages;
555+
BlockNumberrelpages;
556+
doublereltuples;
557+
BlockNumberrelallvisible;
558+
doubledensity;
559+
560+
/* it should have storage, so we can call the smgr */
561+
curpages=RelationGetNumberOfBlocks(rel);
562+
563+
/* coerce values in pg_class to more desirable types */
564+
relpages= (BlockNumber)rel->rd_rel->relpages;
565+
reltuples= (double)rel->rd_rel->reltuples;
566+
relallvisible= (BlockNumber)rel->rd_rel->relallvisible;
567+
568+
/*
569+
* HACK: if the relation has never yet been vacuumed, use a minimum size
570+
* estimate of 10 pages. The idea here is to avoid assuming a
571+
* newly-created table is really small, even if it currently is, because
572+
* that may not be true once some data gets loaded into it. Once a vacuum
573+
* or analyze cycle has been done on it, it's more reasonable to believe
574+
* the size is somewhat stable.
575+
*
576+
* (Note that this is only an issue if the plan gets cached and used again
577+
* after the table has been filled. What we're trying to avoid is using a
578+
* nestloop-type plan on a table that has grown substantially since the
579+
* plan was made. Normally, autovacuum/autoanalyze will occur once enough
580+
* inserts have happened and cause cached-plan invalidation; but that
581+
* doesn't happen instantaneously, and it won't happen at all for cases
582+
* such as temporary tables.)
583+
*
584+
* We approximate "never vacuumed" by "has relpages = 0", which means this
585+
* will also fire on genuinely empty relations. Not great, but
586+
* fortunately that's a seldom-seen case in the real world, and it
587+
* shouldn't degrade the quality of the plan too much anyway to err in
588+
* this direction.
589+
*
590+
* If the table has inheritance children, we don't apply this heuristic.
591+
* Totally empty parent tables are quite common, so we should be willing
592+
* to believe that they are empty.
593+
*/
594+
if (curpages<10&&
595+
relpages==0&&
596+
!rel->rd_rel->relhassubclass)
597+
curpages=10;
598+
599+
/* report estimated # pages */
600+
*pages=curpages;
601+
/* quick exit if rel is clearly empty */
602+
if (curpages==0)
603+
{
604+
*tuples=0;
605+
*allvisfrac=0;
606+
return;
607+
}
608+
609+
/* estimate number of tuples from previous tuple density */
610+
if (relpages>0)
611+
density=reltuples / (double)relpages;
612+
else
613+
{
614+
/*
615+
* When we have no data because the relation was truncated, estimate
616+
* tuple width from attribute datatypes. We assume here that the
617+
* pages are completely full, which is OK for tables (since they've
618+
* presumably not been VACUUMed yet) but is probably an overestimate
619+
* for indexes. Fortunately get_relation_info() can clamp the
620+
* overestimate to the parent table's size.
621+
*
622+
* Note: this code intentionally disregards alignment considerations,
623+
* because (a) that would be gilding the lily considering how crude
624+
* the estimate is, (b) it creates platform dependencies in the
625+
* default plans which are kind of a headache for regression testing,
626+
* and (c) different table AMs might use different padding schemes.
627+
*/
628+
int32tuple_width;
629+
630+
tuple_width=get_rel_data_width(rel,attr_widths);
631+
tuple_width+=overhead_bytes_per_tuple;
632+
/* note: integer division is intentional here */
633+
density=usable_bytes_per_page /tuple_width;
634+
}
635+
*tuples=rint(density* (double)curpages);
636+
637+
/*
638+
* We use relallvisible as-is, rather than scaling it up like we do for
639+
* the pages and tuples counts, on the theory that any pages added since
640+
* the last VACUUM are most likely not marked all-visible. But costsize.c
641+
* wants it converted to a fraction.
642+
*/
643+
if (relallvisible==0||curpages <=0)
644+
*allvisfrac=0;
645+
elseif ((double)relallvisible >=curpages)
646+
*allvisfrac=1;
647+
else
648+
*allvisfrac= (double)relallvisible /curpages;
649+
}

‎src/include/access/tableam.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1727,6 +1727,20 @@ extern void table_block_parallelscan_startblock_init(Relation rel,
17271727
ParallelBlockTableScanDescpbscan);
17281728

17291729

1730+
/* ----------------------------------------------------------------------------
1731+
* Helper functions to implement relation sizing for block oriented AMs.
1732+
* ----------------------------------------------------------------------------
1733+
*/
1734+
1735+
externuint64table_block_relation_size(Relationrel,ForkNumberforkNumber);
1736+
externvoidtable_block_relation_estimate_size(Relationrel,
1737+
int32*attr_widths,
1738+
BlockNumber*pages,
1739+
double*tuples,
1740+
double*allvisfrac,
1741+
Sizeoverhead_bytes_per_tuple,
1742+
Sizeusable_bytes_per_page);
1743+
17301744
/* ----------------------------------------------------------------------------
17311745
* Functions in tableamapi.c
17321746
* ----------------------------------------------------------------------------

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp