1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-08 11:42:09 +03:00

Support index-only scans using the visibility map to avoid heap fetches.

When a btree index contains all columns required by the query, and the
visibility map shows that all tuples on a target heap page are
visible-to-all, we don't need to fetch that heap page.  This patch depends
on the previous patches that made the visibility map reliable.

There's a fair amount left to do here, notably trying to figure out a less
chintzy way of estimating the cost of an index-only scan, but the core
functionality seems ready to commit.

Robert Haas and Ibrar Ahmed, with some previous work by Heikki Linnakangas.
This commit is contained in:
Tom Lane
2011-10-07 20:13:02 -04:00
parent caa1054df8
commit a2822fb933
34 changed files with 704 additions and 203 deletions

View File

@ -34,6 +34,12 @@ typedef struct
int sublevels_up;
} pull_varnos_context;
typedef struct
{
Bitmapset *varattnos;
Index varno;
} pull_varattnos_context;
typedef struct
{
int var_location;
@ -70,7 +76,7 @@ typedef struct
static bool pull_varnos_walker(Node *node,
pull_varnos_context *context);
static bool pull_varattnos_walker(Node *node, Bitmapset **varattnos);
static bool pull_varattnos_walker(Node *node, pull_varattnos_context *context);
static bool contain_var_clause_walker(Node *node, void *context);
static bool contain_vars_of_level_walker(Node *node, int *sublevels_up);
static bool locate_var_of_level_walker(Node *node,
@ -177,23 +183,31 @@ pull_varnos_walker(Node *node, pull_varnos_context *context)
* pull_varattnos
* Find all the distinct attribute numbers present in an expression tree,
* and add them to the initial contents of *varattnos.
* Only Vars that reference RTE 1 of rtable level zero are considered.
* Only Vars of the given varno and rtable level zero are considered.
*
* Attribute numbers are offset by FirstLowInvalidHeapAttributeNumber so that
* we can include system attributes (e.g., OID) in the bitmap representation.
*
* Currently, this does not support subqueries nor expressions containing
* references to multiple tables; not needed since it's only applied to
* index expressions and predicates.
* Currently, this does not support unplanned subqueries; that is not needed
* for current uses. It will handle already-planned SubPlan nodes, though,
* looking into only the "testexpr" and the "args" list. (The subplan cannot
* contain any other references to Vars of the current level.)
*/
void
pull_varattnos(Node *node, Bitmapset **varattnos)
pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
{
(void) pull_varattnos_walker(node, varattnos);
pull_varattnos_context context;
context.varattnos = *varattnos;
context.varno = varno;
(void) pull_varattnos_walker(node, &context);
*varattnos = context.varattnos;
}
static bool
pull_varattnos_walker(Node *node, Bitmapset **varattnos)
pull_varattnos_walker(Node *node, pull_varattnos_context *context)
{
if (node == NULL)
return false;
@ -201,17 +215,18 @@ pull_varattnos_walker(Node *node, Bitmapset **varattnos)
{
Var *var = (Var *) node;
Assert(var->varno == 1);
*varattnos = bms_add_member(*varattnos,
var->varattno - FirstLowInvalidHeapAttributeNumber);
if (var->varno == context->varno && var->varlevelsup == 0)
context->varattnos =
bms_add_member(context->varattnos,
var->varattno - FirstLowInvalidHeapAttributeNumber);
return false;
}
/* Should not find a subquery or subplan */
/* Should not find an unplanned subquery */
Assert(!IsA(node, Query));
Assert(!IsA(node, SubPlan));
return expression_tree_walker(node, pull_varattnos_walker,
(void *) varattnos);
(void *) context);
}