Index-only quals

From: Heikki Linnakangas <heikki(dot)linnakangas(at)enterprisedb(dot)com>
To: PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org>
Subject: Index-only quals
Date: 2009-07-14 09:04:56
Message-ID: 4A5C4A38.4020009@enterprisedb.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

I already posted the patch to satisfy quals using data from index
yesterday
(http://archives.postgresql.org/message-id/4A5B5386.3070100@enterprisedb.com),
but here's some more thoughts about the patch:

1, The patch adds a flag to IndexScanDesc (needIndexTuple) that you can
set to request the indexam to return index tuples. If set, amgettuple
stores the current index tuple to a new xs_itup field in IndexScanDesc.

needIndexTuple is just a humble request - the indexam can ignore it if
it can't return the index tuple. For example in B-tree, if new tuples
are inserted on the leaf page, we fail to find the index tuple and bail
out. Alternatively, b-tree could copy all the matching tuples to private
memory when we step to next page, like it copies all the TIDs, but that
seems expensive.

We already discussed how to know which indexams and which opclasses can
return index tuples at all. I'm thinking of just adding a new boolean
column to pg_am. In GiST, it depends on the opclass whether it can
regurgitate the original data, but I'm only going to support b-trees for
now so I'd like to not bother with a more complex scheme yet.

2. Before the patch, there is two ways an index scan node can check
restriction clauses. If the restriction matches an index column and uses
a suitable operator, it can be used as an index key. All other
restrictions are handled by fetching the heap tuple, and using ExecQual.
This patch introduces a third way: fetch the index tuple, and use
ExecQual against it. I'm calling these quals "index-only quals". In
EXPLAIN, they are shown as "Index-Only Filters".

In find_usable_indexes(), we scan through restrictinfos and pick those
that are not used as index keys, but can be evaluated using data from
the index. The existence of such quals affects the estimated cost, and
whether we consider using the index at all. The cost estimation is quite
dummy still, I haven't given it much thought or testing yet.

create_indexscan_plan() contains roughly the same logic as
find_usable_indexes(), I couldn't figure out a good way to eliminate the
duplication. Perhaps I'm doing this at the wrong place, I hope someone
has ideas on how this should be done.

Index-only quals are stored in IndexScan in form where varattnos of Vars
have been replaced with varattnos of the index. This is the same format
used for "indexqual". The comments in planmain.h suggest that we might
want to refactor that:

* indexqual has the same form, but the expressions have been commuted if
* necessary to put the indexkeys on the left, and the indexkeys are
replaced
* by Var nodes identifying the index columns (varattno is the index column
* position, not the base table's column, even though varno is for the base
* table). This is a bit hokey ... would be cleaner to use a special-purpose
* node type that could not be mistaken for a regular Var. But it will do
* for now. (We do the same for indexonlyqual)
The executor needs the index-only quals in form that can be evaluated

It works as it is, but maybe we should bite that bullet now. As this
work continues to support returning data from index without accessing
the heap at all, we'll need to have an index-only equivalent of the
target list as well.

Replacing the Vars that refer to heap atts with index atts is done in
new make_indexonly_expr() function. The logic is almost identical to
fix_indexqual_references(). They probably should be merged, but are
separate now.

--
Heikki Linnakangas
EnterpriseDB http://www.enterprisedb.com

Browse pgsql-hackers by date

  From Date Subject
Next Message Simon Riggs 2009-07-14 09:39:18 Comments on automatic DML routing and explicit partitioning subcommands
Previous Message Simon Riggs 2009-07-14 08:52:25 Re: Index-only scans