Thread: Scan Keys

Scan Keys

From
Greg Stark
Date:
I'm a bit confused about how scan keys work. Is there any simple way given a
list of Datums of the same type as the index tuple attributes to get all
matching index entries? This is for a non-system index.

It seems like the only place in the code where non-system index lookups are
done is nodeIndexscan.c where it has the strategy number, subtype, and
function to use from the work that's previously been done on the expression.

But I want to do something more like what btree does inside btinsert where it
knows that no cross-type functions could be necessary and the only function of
interest is equality.

I tried just using index_getprocinfo(...,BTORDER) with InvalidStrategy like
btree does but _bt_preprocess_keys runs into problems without a valid strategy
number. And in any case that would be btree specific which seems like it ought
not be necessary.

-- 
greg



Re: Scan Keys

From
Martijn van Oosterhout
Date:
On Wed, Jul 05, 2006 at 12:00:05PM -0400, Greg Stark wrote:
>
> I'm a bit confused about how scan keys work. Is there any simple way given a
> list of Datums of the same type as the index tuple attributes to get all
> matching index entries? This is for a non-system index.

A scankey determines which values you want. It consists of a value and
an operator. Using that the index code returns tuples matching.

So if you want all values equal to 4, you pass '4' for the Datum and
the Equal strategy, with the operator as '='.

The info you need is in the operator class. In a sense you do need to
know the type of index you're scanning, not all indexes use the same
strategy numbers.

> But I want to do something more like what btree does inside btinsert where it
> knows that no cross-type functions could be necessary and the only function of
> interest is equality.

By the time the btree code gets involved, everything in the scankey
should already have been filled in.  I don't beleive the code actually
checks if the operator is of the type you specify.

Hope this helps a bit,
--
Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
> From each according to his ability. To each according to his ability to litigate.

Re: Scan Keys

From
Greg Stark
Date:
Martijn van Oosterhout <kleptog@svana.org> writes:

> The info you need is in the operator class. In a sense you do need to
> know the type of index you're scanning, not all indexes use the same
> strategy numbers.

Well what was tripping me up was figuring out the operator class. I just
realized it's in the index's Relation object. 

But yes what you describe is really a problem. Even given the operator class
there's no way for me to know which strategy number to pick. There might not
be any strategy number for equals in which case I'm in trouble.

-- 
greg



Re: Scan Keys

From
Martijn van Oosterhout
Date:
On Wed, Jul 05, 2006 at 09:14:21PM -0400, Greg Stark wrote:
> Well what was tripping me up was figuring out the operator class. I just
> realized it's in the index's Relation object.
>
> But yes what you describe is really a problem. Even given the operator class
> there's no way for me to know which strategy number to pick. There might not
> be any strategy number for equals in which case I'm in trouble.

Well yes, that's an issue. Currently it's assumed by various parts of
the backend that the EqualStrategy operator of a btree operator class
is what you can use to decide what's equal. Although it's not really
necessary, there is currently nothing else in the system that really
tells you the answer to the question you ask...

Have a nice day,
--
Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
> From each according to his ability. To each according to his ability to litigate.

Re: Scan Keys

From
Tom Lane
Date:
Greg Stark <gsstark@mit.edu> writes:
> I'm a bit confused about how scan keys work. Is there any simple way given a
> list of Datums of the same type as the index tuple attributes to get all
> matching index entries? This is for a non-system index.

Define "matching".

> I tried just using index_getprocinfo(...,BTORDER) with InvalidStrategy like
> btree does but _bt_preprocess_keys runs into problems without a valid strategy
> number. And in any case that would be btree specific which seems like it ought
> not be necessary.

There's no particularly good reason to suppose that a non-btree index
necessarily supports equality probes at all.  For instance if you're
using GIST or GIN for full-text searching, the index might only know
about component words, not the whole strings that are in the table.
Opclasses designed for spatial databases might conceivably not have
equality either (though that's a bit more of a stretch).

As Martijn pointed out, we rely on btree-opclass equality as the main
means of deciding what equality "really is".  I don't think it'd be
wise to insist that every index opclass, no matter what its purpose,
has to include an equality operator.
        regards, tom lane


Re: Scan Keys

From
Greg Stark
Date:
Tom Lane <tgl@sss.pgh.pa.us> writes:

> > I tried just using index_getprocinfo(...,BTORDER) with InvalidStrategy like
> > btree does but _bt_preprocess_keys runs into problems without a valid strategy
> > number. And in any case that would be btree specific which seems like it ought
> > not be necessary.
> 
> There's no particularly good reason to suppose that a non-btree index
> necessarily supports equality probes at all.  For instance if you're
> using GIST or GIN for full-text searching, the index might only know
> about component words, not the whole strings that are in the table.
> Opclasses designed for spatial databases might conceivably not have
> equality either (though that's a bit more of a stretch).

AFAIK even GIST indexes can fetch me a reasonably limited list of tuples that
might be equal. It might include significantly more tuples than just what I'm
looking for but it's much better than doing a full index scan.

But on that note, is it ok to use the bulkdelete index AM methods for
non-vacuum purposes as long as there's only one such process running at a
time? Presumably that means taking an ShareUpdateExclusiveLock on the
indexrelation or a ExclusiveLock on the pg_index line?

> As Martijn pointed out, we rely on btree-opclass equality as the main
> means of deciding what equality "really is".  I don't think it'd be
> wise to insist that every index opclass, no matter what its purpose,
> has to include an equality operator.

I'm having trouble picturing any useful index where there's no operator close
to equality. But I'll concede that that may be a failure of my imagination :)

-- 
greg



Re: Scan Keys

From
Tom Lane
Date:
Greg Stark <gsstark@mit.edu> writes:
> But on that note, is it ok to use the bulkdelete index AM methods for
> non-vacuum purposes

Um, what would those be?

ambulkdelete and amvacuumcleanup are most certainly not designed to be
used in any context other than VACUUM.  You might be able to abuse them
for some other purpose, but don't expect a warranty.
        regards, tom lane


Re: Scan Keys

From
Greg Stark
Date:
Tom Lane <tgl@sss.pgh.pa.us> writes:

> Greg Stark <gsstark@mit.edu> writes:
> > But on that note, is it ok to use the bulkdelete index AM methods for
> > non-vacuum purposes
> 
> Um, what would those be?

I'm sure with a little work I can imagine lots of reasons to want to pull out
all the index tuples from an index other than vacuum. I can't actually name
any right now, but I'm sure I'll think of some :)

> ambulkdelete and amvacuumcleanup are most certainly not designed to be
> used in any context other than VACUUM.  You might be able to abuse them
> for some other purpose, but don't expect a warranty.

What I'm doing now is calling ambulkdelete with a callback that returns false
for every tuple and stuffs the item pointer into a data structure. It seems to
be working but I haven't tested it thoroughly yet.

I'm worried that ambulkdelete might have side effects on the index that aren't
obvious. Other than bumping the vacuum cycle id I don't see any in a quick
scan of the btree code. But I could have missed something or other access
methods could behave differently.

I would be happier with a generic "index sequential scan" interface. I realize
the cycle id trick restricts any such api to a single scanner at a time which
is fine for my purposes.

Actually is that really true? Wouldn't the cycle id setup work fine if a
subsequent scan started and the cycle id was bumped a second time? If you find
a page that was split with a cycle id greater than yours then you still know
it was split after you started. As long as the cycle id doesn't wrap while a
scan is proceeding it should be fine. Perhaps tagging the split pages with the
xid of the most recent scan instead of a separate cycle id concept?

-- 
greg