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

Commit27bc177

Browse files
committed
Generalize relation analyze in table AM interface
Currently, there is just one algorithm for sampling tuples from a table writtenin acquire_sample_rows(). Custom table AM can just redefine the way to get thenext block/tuple by implementing scan_analyze_next_block() andscan_analyze_next_tuple() API functions.This approach doesn't seem general enough. For instance, it's unclear how tosample this way index-organized tables. This commit allows table AM toencapsulate the whole sampling algorithm (currently implemented inacquire_sample_rows()) into the relation_analyze() API function.Discussion:https://postgr.es/m/CAPpHfdurb9ycV8udYqM%3Do0sPS66PJ4RCBM1g-bBpvzUfogY0EA%40mail.gmail.comReviewed-by: Pavel Borisov, Matthias van de Meent
1 parentb154d8a commit27bc177

File tree

7 files changed

+100
-125
lines changed

7 files changed

+100
-125
lines changed

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

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ static TM_Result heapam_tuple_lock(Relation relation, ItemPointer tid,
5050
CommandIdcid,LockTupleModemode,
5151
LockWaitPolicywait_policy,uint8flags,
5252
TM_FailureData*tmfd);
53-
5453
staticvoidreform_and_rewrite_tuple(HeapTupletuple,
5554
RelationOldHeap,RelationNewHeap,
5655
Datum*values,bool*isnull,RewriteStaterwstate);
@@ -1052,7 +1051,15 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
10521051
pfree(isnull);
10531052
}
10541053

1055-
staticbool
1054+
/*
1055+
* Prepare to analyze block `blockno` of `scan`. The scan has been started
1056+
* with SO_TYPE_ANALYZE option.
1057+
*
1058+
* This routine holds a buffer pin and lock on the heap page. They are held
1059+
* until heapam_scan_analyze_next_tuple() returns false. That is until all the
1060+
* items of the heap page are analyzed.
1061+
*/
1062+
void
10561063
heapam_scan_analyze_next_block(TableScanDescscan,BlockNumberblockno,
10571064
BufferAccessStrategybstrategy)
10581065
{
@@ -1072,12 +1079,19 @@ heapam_scan_analyze_next_block(TableScanDesc scan, BlockNumber blockno,
10721079
hscan->rs_cbuf=ReadBufferExtended(scan->rs_rd,MAIN_FORKNUM,
10731080
blockno,RBM_NORMAL,bstrategy);
10741081
LockBuffer(hscan->rs_cbuf,BUFFER_LOCK_SHARE);
1075-
1076-
/* in heap all blocks can contain tuples, so always return true */
1077-
return true;
10781082
}
10791083

1080-
staticbool
1084+
/*
1085+
* Iterate over tuples in the block selected with
1086+
* heapam_scan_analyze_next_block(). If a tuple that's suitable for sampling
1087+
* is found, true is returned and a tuple is stored in `slot`. When no more
1088+
* tuples for sampling, false is returned and the pin and lock acquired by
1089+
* heapam_scan_analyze_next_block() are released.
1090+
*
1091+
* *liverows and *deadrows are incremented according to the encountered
1092+
* tuples.
1093+
*/
1094+
bool
10811095
heapam_scan_analyze_next_tuple(TableScanDescscan,TransactionIdOldestXmin,
10821096
double*liverows,double*deadrows,
10831097
TupleTableSlot*slot)
@@ -2637,10 +2651,9 @@ static const TableAmRoutine heapam_methods = {
26372651
.relation_copy_data=heapam_relation_copy_data,
26382652
.relation_copy_for_cluster=heapam_relation_copy_for_cluster,
26392653
.relation_vacuum=heap_vacuum_rel,
2640-
.scan_analyze_next_block=heapam_scan_analyze_next_block,
2641-
.scan_analyze_next_tuple=heapam_scan_analyze_next_tuple,
26422654
.index_build_range_scan=heapam_index_build_range_scan,
26432655
.index_validate_scan=heapam_index_validate_scan,
2656+
.relation_analyze=heapam_analyze,
26442657

26452658
.free_rd_amcache=NULL,
26462659
.relation_size=table_block_relation_size,

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,6 @@ GetTableAmRoutine(Oid amhandler)
8181
Assert(routine->relation_copy_data!=NULL);
8282
Assert(routine->relation_copy_for_cluster!=NULL);
8383
Assert(routine->relation_vacuum!=NULL);
84-
Assert(routine->scan_analyze_next_block!=NULL);
85-
Assert(routine->scan_analyze_next_tuple!=NULL);
8684
Assert(routine->index_build_range_scan!=NULL);
8785
Assert(routine->index_validate_scan!=NULL);
8886

‎src/backend/commands/analyze.c

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include<math.h>
1818

1919
#include"access/detoast.h"
20+
#include"access/heapam.h"
2021
#include"access/genam.h"
2122
#include"access/multixact.h"
2223
#include"access/relation.h"
@@ -190,10 +191,9 @@ analyze_rel(Oid relid, RangeVar *relation,
190191
if (onerel->rd_rel->relkind==RELKIND_RELATION||
191192
onerel->rd_rel->relkind==RELKIND_MATVIEW)
192193
{
193-
/* Regular table, so we'll use the regular row acquisition function */
194-
acquirefunc=acquire_sample_rows;
195-
/* Also get regular table's size */
196-
relpages=RelationGetNumberOfBlocks(onerel);
194+
/* Use row acquisition function provided by table AM */
195+
table_relation_analyze(onerel,&acquirefunc,
196+
&relpages,vac_strategy);
197197
}
198198
elseif (onerel->rd_rel->relkind==RELKIND_FOREIGN_TABLE)
199199
{
@@ -1103,15 +1103,15 @@ examine_attribute(Relation onerel, int attnum, Node *index_expr)
11031103
}
11041104

11051105
/*
1106-
* acquire_sample_rows -- acquire a random sample of rows from thetable
1106+
* acquire_sample_rows -- acquire a random sample of rows from theheap
11071107
*
11081108
* Selected rows are returned in the caller-allocated array rows[], which
11091109
* must have at least targrows entries.
11101110
* The actual number of rows selected is returned as the function result.
1111-
* We also estimate the total numbers of live and dead rows in thetable,
1111+
* We also estimate the total numbers of live and dead rows in theheap,
11121112
* and return them into *totalrows and *totaldeadrows, respectively.
11131113
*
1114-
* The returned list of tuples is in order by physical position in thetable.
1114+
* The returned list of tuples is in order by physical position in theheap.
11151115
* (We will rely on this later to derive correlation estimates.)
11161116
*
11171117
* As of May 2004 we use a new two-stage method: Stage one selects up
@@ -1133,7 +1133,7 @@ examine_attribute(Relation onerel, int attnum, Node *index_expr)
11331133
* look at a statistically unbiased set of blocks, we should get
11341134
* unbiased estimates of the average numbers of live and dead rows per
11351135
* block. The previous sampling method put too much credence in the row
1136-
* density near the start of thetable.
1136+
* density near the start of theheap.
11371137
*/
11381138
staticint
11391139
acquire_sample_rows(Relationonerel,intelevel,
@@ -1184,7 +1184,7 @@ acquire_sample_rows(Relation onerel, int elevel,
11841184
/* Prepare for sampling rows */
11851185
reservoir_init_selection_state(&rstate,targrows);
11861186

1187-
scan=table_beginscan_analyze(onerel);
1187+
scan=heap_beginscan(onerel,NULL,0,NULL,NULL,SO_TYPE_ANALYZE);
11881188
slot=table_slot_create(onerel,NULL);
11891189

11901190
#ifdefUSE_PREFETCH
@@ -1214,7 +1214,6 @@ acquire_sample_rows(Relation onerel, int elevel,
12141214
/* Outer loop over blocks to sample */
12151215
while (BlockSampler_HasMore(&bs))
12161216
{
1217-
boolblock_accepted;
12181217
BlockNumbertargblock=BlockSampler_Next(&bs);
12191218
#ifdefUSE_PREFETCH
12201219
BlockNumberprefetch_targblock=InvalidBlockNumber;
@@ -1230,29 +1229,19 @@ acquire_sample_rows(Relation onerel, int elevel,
12301229

12311230
vacuum_delay_point();
12321231

1233-
block_accepted=table_scan_analyze_next_block(scan,targblock,vac_strategy);
1232+
heapam_scan_analyze_next_block(scan,targblock,vac_strategy);
12341233

12351234
#ifdefUSE_PREFETCH
12361235

12371236
/*
12381237
* When pre-fetching, after we get a block, tell the kernel about the
12391238
* next one we will want, if there's any left.
1240-
*
1241-
* We want to do this even if the table_scan_analyze_next_block() call
1242-
* above decides against analyzing the block it picked.
12431239
*/
12441240
if (prefetch_maximum&&prefetch_targblock!=InvalidBlockNumber)
12451241
PrefetchBuffer(scan->rs_rd,MAIN_FORKNUM,prefetch_targblock);
12461242
#endif
12471243

1248-
/*
1249-
* Don't analyze if table_scan_analyze_next_block() indicated this
1250-
* block is unsuitable for analyzing.
1251-
*/
1252-
if (!block_accepted)
1253-
continue;
1254-
1255-
while (table_scan_analyze_next_tuple(scan,OldestXmin,&liverows,&deadrows,slot))
1244+
while (heapam_scan_analyze_next_tuple(scan,OldestXmin,&liverows,&deadrows,slot))
12561245
{
12571246
/*
12581247
* The first targrows sample rows are simply copied into the
@@ -1302,7 +1291,7 @@ acquire_sample_rows(Relation onerel, int elevel,
13021291
}
13031292

13041293
ExecDropSingleTupleTableSlot(slot);
1305-
table_endscan(scan);
1294+
heap_endscan(scan);
13061295

13071296
/*
13081297
* If we didn't find as many tuples as we wanted then we're done. No sort
@@ -1373,6 +1362,19 @@ compare_rows(const void *a, const void *b, void *arg)
13731362
return0;
13741363
}
13751364

1365+
/*
1366+
* heapam_analyze -- implementation of relation_analyze() table access method
1367+
* callback for heap
1368+
*/
1369+
void
1370+
heapam_analyze(Relationrelation,AcquireSampleRowsFunc*func,
1371+
BlockNumber*totalpages,BufferAccessStrategybstrategy)
1372+
{
1373+
*func=acquire_sample_rows;
1374+
*totalpages=RelationGetNumberOfBlocks(relation);
1375+
vac_strategy=bstrategy;
1376+
}
1377+
13761378

13771379
/*
13781380
* acquire_inherited_sample_rows -- acquire sample rows from inheritance tree
@@ -1462,9 +1464,9 @@ acquire_inherited_sample_rows(Relation onerel, int elevel,
14621464
if (childrel->rd_rel->relkind==RELKIND_RELATION||
14631465
childrel->rd_rel->relkind==RELKIND_MATVIEW)
14641466
{
1465-
/*Regular table, so use the regular row acquisition function */
1466-
acquirefunc=acquire_sample_rows;
1467-
relpages=RelationGetNumberOfBlocks(childrel);
1467+
/*Use row acquisition function provided by table AM */
1468+
table_relation_analyze(childrel,&acquirefunc,
1469+
&relpages,vac_strategy);
14681470
}
14691471
elseif (childrel->rd_rel->relkind==RELKIND_FOREIGN_TABLE)
14701472
{

‎src/include/access/heapam.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,15 @@ extern bool HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple);
369369
externboolHeapTupleIsSurelyDead(HeapTuplehtup,
370370
structGlobalVisState*vistest);
371371

372+
/* in heap/heapam_handler.c*/
373+
externvoidheapam_scan_analyze_next_block(TableScanDescscan,
374+
BlockNumberblockno,
375+
BufferAccessStrategybstrategy);
376+
externboolheapam_scan_analyze_next_tuple(TableScanDescscan,
377+
TransactionIdOldestXmin,
378+
double*liverows,double*deadrows,
379+
TupleTableSlot*slot);
380+
372381
/*
373382
* To avoid leaking too much knowledge about reorderbuffer implementation
374383
* details this is implemented in reorderbuffer.c not heapam_visibility.c

‎src/include/access/tableam.h

Lines changed: 22 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include"access/relscan.h"
2121
#include"access/sdir.h"
2222
#include"access/xact.h"
23+
#include"commands/vacuum.h"
2324
#include"executor/tuptable.h"
2425
#include"utils/rel.h"
2526
#include"utils/snapshot.h"
@@ -658,41 +659,6 @@ typedef struct TableAmRoutine
658659
structVacuumParams*params,
659660
BufferAccessStrategybstrategy);
660661

661-
/*
662-
* Prepare to analyze block `blockno` of `scan`. The scan has been started
663-
* with table_beginscan_analyze(). See also
664-
* table_scan_analyze_next_block().
665-
*
666-
* The callback may acquire resources like locks that are held until
667-
* table_scan_analyze_next_tuple() returns false. It e.g. can make sense
668-
* to hold a lock until all tuples on a block have been analyzed by
669-
* scan_analyze_next_tuple.
670-
*
671-
* The callback can return false if the block is not suitable for
672-
* sampling, e.g. because it's a metapage that could never contain tuples.
673-
*
674-
* XXX: This obviously is primarily suited for block-based AMs. It's not
675-
* clear what a good interface for non block based AMs would be, so there
676-
* isn't one yet.
677-
*/
678-
bool(*scan_analyze_next_block) (TableScanDescscan,
679-
BlockNumberblockno,
680-
BufferAccessStrategybstrategy);
681-
682-
/*
683-
* See table_scan_analyze_next_tuple().
684-
*
685-
* Not every AM might have a meaningful concept of dead rows, in which
686-
* case it's OK to not increment *deadrows - but note that that may
687-
* influence autovacuum scheduling (see comment for relation_vacuum
688-
* callback).
689-
*/
690-
bool(*scan_analyze_next_tuple) (TableScanDescscan,
691-
TransactionIdOldestXmin,
692-
double*liverows,
693-
double*deadrows,
694-
TupleTableSlot*slot);
695-
696662
/* see table_index_build_range_scan for reference about parameters */
697663
double(*index_build_range_scan) (Relationtable_rel,
698664
Relationindex_rel,
@@ -713,6 +679,12 @@ typedef struct TableAmRoutine
713679
Snapshotsnapshot,
714680
structValidateIndexState*state);
715681

682+
/* See table_relation_analyze() */
683+
void(*relation_analyze) (Relationrelation,
684+
AcquireSampleRowsFunc*func,
685+
BlockNumber*totalpages,
686+
BufferAccessStrategybstrategy);
687+
716688

717689
/* ------------------------------------------------------------------------
718690
* Miscellaneous functions.
@@ -1008,19 +980,6 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
1008980
returnrel->rd_tableam->scan_begin(rel,snapshot,0,NULL,NULL,flags);
1009981
}
1010982

1011-
/*
1012-
* table_beginscan_analyze is an alternative entry point for setting up a
1013-
* TableScanDesc for an ANALYZE scan. As with bitmap scans, it's worth using
1014-
* the same data structure although the behavior is rather different.
1015-
*/
1016-
staticinlineTableScanDesc
1017-
table_beginscan_analyze(Relationrel)
1018-
{
1019-
uint32flags=SO_TYPE_ANALYZE;
1020-
1021-
returnrel->rd_tableam->scan_begin(rel,NULL,0,NULL,NULL,flags);
1022-
}
1023-
1024983
/*
1025984
* End relation scan.
1026985
*/
@@ -1746,42 +1705,6 @@ table_relation_vacuum(Relation rel, struct VacuumParams *params,
17461705
rel->rd_tableam->relation_vacuum(rel,params,bstrategy);
17471706
}
17481707

1749-
/*
1750-
* Prepare to analyze block `blockno` of `scan`. The scan needs to have been
1751-
* started with table_beginscan_analyze(). Note that this routine might
1752-
* acquire resources like locks that are held until
1753-
* table_scan_analyze_next_tuple() returns false.
1754-
*
1755-
* Returns false if block is unsuitable for sampling, true otherwise.
1756-
*/
1757-
staticinlinebool
1758-
table_scan_analyze_next_block(TableScanDescscan,BlockNumberblockno,
1759-
BufferAccessStrategybstrategy)
1760-
{
1761-
returnscan->rs_rd->rd_tableam->scan_analyze_next_block(scan,blockno,
1762-
bstrategy);
1763-
}
1764-
1765-
/*
1766-
* Iterate over tuples in the block selected with
1767-
* table_scan_analyze_next_block() (which needs to have returned true, and
1768-
* this routine may not have returned false for the same block before). If a
1769-
* tuple that's suitable for sampling is found, true is returned and a tuple
1770-
* is stored in `slot`.
1771-
*
1772-
* *liverows and *deadrows are incremented according to the encountered
1773-
* tuples.
1774-
*/
1775-
staticinlinebool
1776-
table_scan_analyze_next_tuple(TableScanDescscan,TransactionIdOldestXmin,
1777-
double*liverows,double*deadrows,
1778-
TupleTableSlot*slot)
1779-
{
1780-
returnscan->rs_rd->rd_tableam->scan_analyze_next_tuple(scan,OldestXmin,
1781-
liverows,deadrows,
1782-
slot);
1783-
}
1784-
17851708
/*
17861709
* table_index_build_scan - scan the table to find tuples to be indexed
17871710
*
@@ -1887,6 +1810,21 @@ table_index_validate_scan(Relation table_rel,
18871810
state);
18881811
}
18891812

1813+
/*
1814+
* table_relation_analyze - fill the infromation for a sampling statistics
1815+
*acquisition
1816+
*
1817+
* The pointer to a function that will collect sample rows from the table
1818+
* should be stored to `*func`, plus the estimated size of the table in pages
1819+
* should br stored to `*totalpages`.
1820+
*/
1821+
staticinlinevoid
1822+
table_relation_analyze(Relationrelation,AcquireSampleRowsFunc*func,
1823+
BlockNumber*totalpages,BufferAccessStrategybstrategy)
1824+
{
1825+
relation->rd_tableam->relation_analyze(relation,func,
1826+
totalpages,bstrategy);
1827+
}
18901828

18911829
/* ----------------------------------------------------------------------------
18921830
* Miscellaneous functionality

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp