From bf3dbb5881e9b886ee9fe84bca2153c698eea885 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 27 Mar 2005 23:53:05 +0000 Subject: First steps towards index scans with heap access decoupled from index access: define new index access method functions 'amgetmulti' that can fetch multiple TIDs per call. (The functions exist but are totally untested as yet.) Since I was modifying pg_am anyway, remove the no-longer-needed 'rel' parameter from amcostestimate functions, and also remove the vestigial amowner column that was creating useless work for Alvaro's shared-object-dependencies project. Initdb forced due to changes in pg_am. --- doc/src/sgml/catalogs.sgml | 28 +++++++-------- doc/src/sgml/indexam.sgml | 85 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 74 insertions(+), 39 deletions(-) (limited to 'doc/src') diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 7cfca6f1182..2dc8b300956 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -1,6 +1,6 @@ @@ -316,13 +316,6 @@ Name of the access method - - amowner - int4 - pg_shadow.usesysid - User ID of the owner (currently not used) - - amstrategies int2 @@ -374,24 +367,31 @@ - amgettuple + aminsert regproc pg_proc.oid - Next valid tuple function + Insert this tuple function - aminsert + ambeginscan regproc pg_proc.oid - Insert this tuple function + Start new scan function - ambeginscan + amgettuple regproc pg_proc.oid - Start new scan function + Next valid tuple function + + + + amgetmulti + regproc + pg_proc.oid + Fetch multiple tuples function diff --git a/doc/src/sgml/indexam.sgml b/doc/src/sgml/indexam.sgml index d6b83060485..ef1e37a8260 100644 --- a/doc/src/sgml/indexam.sgml +++ b/doc/src/sgml/indexam.sgml @@ -1,5 +1,5 @@ @@ -252,6 +252,28 @@ amgettuple (IndexScanDesc scan, +boolean +amgetmulti (IndexScanDesc scan, + ItemPointer tids, + int32 max_tids, + int32 *returned_tids); + + Fetch multiple tuples in the given scan. Returns TRUE if the scan should + continue, FALSE if no matching tuples remain. tids points to + a caller-supplied array of max_tids + ItemPointerData records, which the call fills with TIDs of + matching tuples. *returned_tids is set to the number of TIDs + actually returned. This can be less than max_tids, or even + zero, even when the return value is TRUE. (This provision allows the + access method to choose the most efficient stopping points in its scan, + for example index page boundaries.) amgetmulti and + amgettuple cannot be used in the same index scan; there + are other restrictions too when using amgetmulti, as explained + in . + + + + void amrescan (IndexScanDesc scan, ScanKey key); @@ -297,7 +319,6 @@ amrestrpos (IndexScanDesc scan); void amcostestimate (Query *root, - RelOptInfo *rel, IndexOptInfo *index, List *indexQuals, Cost *indexStartupCost, @@ -407,6 +428,25 @@ amcostestimate (Query *root, true, insertions or deletions from other backends must be handled as well.) + + Instead of using amgettuple, an index scan can be done with + amgetmulti to fetch multiple tuples per call. This can be + noticeably more efficient than amgettuple because it allows + avoiding lock/unlock cycles within the access method. In principle + amgetmulti should have the same effects as repeated + amgettuple calls, but we impose several restrictions to + simplify matters. In the first place, amgetmulti does not + take a direction argument, and therefore it does not support + backwards scan nor intrascan reversal of direction. The access method + need not support marking or restoring scan positions during an + amgetmulti scan, either. (These restrictions cost little + since it would be difficult to use these features in an + amgetmulti scan anyway: adjusting the caller's buffered + list of TIDs would be complex.) Finally, amgetmulti does + not guarantee any locking of the returned tuples, with implications + spelled out in . + + @@ -515,10 +555,15 @@ amcostestimate (Query *root, and only visit the heap tuples sometime later, requires much less index locking overhead and may allow a more efficient heap access pattern. Per the above analysis, we must use the synchronous approach for - non-MVCC-compliant snapshots, but an asynchronous scan would be safe - for a query using an MVCC snapshot. This possibility is not exploited - as of PostgreSQL 8.0, but it is likely to be - investigated soon. + non-MVCC-compliant snapshots, but an asynchronous scan is workable + for a query using an MVCC snapshot. + + + + In an amgetmulti index scan, the access method need not + guarantee to keep an index pin on any of the returned tuples. (It would be + impractical to pin more than the last one anyway.) Therefore + it is only safe to use such scans with MVCC-compliant snapshots. @@ -611,7 +656,6 @@ amcostestimate (Query *root, void amcostestimate (Query *root, - RelOptInfo *rel, IndexOptInfo *index, List *indexQuals, Cost *indexStartupCost, @@ -632,20 +676,11 @@ amcostestimate (Query *root, - - rel - - - The relation the index is on. - - - - index - The index itself. + The index being considered. @@ -714,19 +749,19 @@ amcostestimate (Query *root, The index access costs should be computed in the units used by - src/backend/optimizer/path/costsize.c: a sequential disk block fetch - has cost 1.0, a nonsequential fetch has cost random_page_cost, and - the cost of processing one index row should usually be taken as - cpu_index_tuple_cost (which is a user-adjustable optimizer parameter). - In addition, an appropriate multiple of cpu_operator_cost should be charged + src/backend/optimizer/path/costsize.c: a sequential + disk block fetch has cost 1.0, a nonsequential fetch has cost + random_page_cost, and the cost of processing one index row + should usually be taken as cpu_index_tuple_cost. In addition, + an appropriate multiple of cpu_operator_cost should be charged for any comparison operators invoked during index processing (especially evaluation of the indexQuals themselves). The access costs should include all disk and CPU costs associated with - scanning the index itself, but NOT the costs of retrieving or processing - the parent-table rows that are identified by the index. + scanning the index itself, but not the costs of retrieving or + processing the parent-table rows that are identified by the index. @@ -764,7 +799,7 @@ amcostestimate (Query *root, *indexSelectivity = clauselist_selectivity(root, indexQuals, - rel->relid, JOIN_INNER); + index->rel->relid, JOIN_INNER); -- cgit v1.2.3