mariadb/storage/rocksdb/rocksdb-range-access.txt
Sergei Petrunia ebfc4e6ad0 Initial commit,
copy of
commit 86587affafe77ef555f7c3839839de44f0f203f3
Author: Tian Xia <tianx@fb.com>
Date:   Tue Oct 4 10:01:52 2016 -0700

    Allow filtering of show commands through admission control
2016-10-06 17:24:09 +00:00

353 lines
8.7 KiB
Text

This file describes how MySQL index navigation commands are translated into
RocksDB index navigation commands.
Index tuples are shown as
( kv )-aaa-pkN
here
* '(kv)' is the 4-byte index number.
* '-' is just for readability
* everything that follows the '-' is mem-comparable form of the key.
In ascii encoding, aaa < bbb < ccc < xxx.
Tuples that start with '#' do not exist in the database. They are only shown
to demonstrate where Seek() calls end up with.
== HA_READ_KEY_EXACT, forward CF ==
(kv-1)-xxx-pk
# ( kv )-aaa <-- "kv-aaa" doesn't exist in the database, but it would be
here.
( kv )-aaa-pk <--- Seek("kv-aaa") will put us here on the next record.
( kv )-aaa-pk2
( kv )-bbb-...
RocksDB calls:
it->Seek(kv);
if (it->Valid() && kd->covers_key(..) && kd->cmp_full_keys(...))
return record.
== HA_READ_KEY_EXACT, backward CF ==
When we need to seek to a tuple that is a prefix of a full key:
(kv+1)-xxx-pk
( kv )-ccc-pk
( kv )-bbb-pk3
( kv )-bbb-pk2
( kv )-bbb-pk1 < -- We need to be here
# ( kv )-bbb <---we call Seek(kv-bbb)
( kv )-aaa-pk ... and end up here. Should call it->Prev().
There is a special case when (kv)-bbb-pk1 is the last record in the CF, and
we get invalid iterator. Then, we need to call SeekToLast().
Another kind of special case is when we need to seek to the full value.
Suppose, the lookup tuple is kv-bbb-pk1:
(kv+1)-xxx-pk
( kv )-ccc-pk
( kv )-bbb-pk3
( kv )-bbb-pk2
( kv )-bbb-pk1 < -- Seek(kv-bbb-pk1)
( kv )-bbb-pk0
Then, Seek(kv-bbb-pk1) will position us exactly the tuple we need, and we
won't need to call it->Prev(). If we get an invalid iterator, there is no
need to call SeekToLast().
RocksDB calls:
it->Seek(tuple);
if (!using_full_key)
{
if (!it->Valid())
it->SeekToLast();
else
it->Prev();
}
if (it->Valid() && kd->covers_key(..) && kd->cmp_full_keys(...))
return record.
== HA_READ_KEY_OR_NEXT, forward CF ==
This is finding min(key) such that key >= lookup_tuple.
If lookup tuple is kv-bbb:
( kv )-aaa-pk
# ( kv )-bbb <-- "kv-bbb" doesn't exist in the database, but it would be
here.
( kv )-bbb-pk1 <--- Seek("kv-bbb") will put us here on the next record.
( kv )-bbb-pk2
( kv )-bbb-...
RocksDB calls:
Seek(kv);
if (it->Valid() && kd->covers_key(..) && kd->cmp_full_keys(...))
return record.
== HA_READ_KEY_OR_NEXT, backward CF ==
When specified key tuple is a key prefix:
(kv+1)-xxx-pk
( kv )-ccc-pk
( kv )-bbb-pk3
( kv )-bbb-pk2
( kv )-bbb-pk1 < -- We need to be here (or above)
# ( kv )-bbb <---we call Seek(kv-bbb)
( kv )-aaa-pk ... and end up here. Should call it->Prev().
There is a special case when (kv)-bbb-pk1 is the last record in the CF, and
we get invalid iterator. Then, we need to call SeekToLast().
Another kind of special case is when we need to seek to the full value.
Suppose, the lookup tuple is kv-bbb-pk1:
(kv+1)-xxx-pk
( kv )-ccc-pk
( kv )-bbb-pk3
( kv )-bbb-pk2
( kv )-bbb-pk1 < -- Seek(kv-bbb-pk1)
( kv )-bbb-pk0
Then, Seek(kv-bbb-pk1) may position us exactly at the tuple we need, and we
won't need to call it->Prev().
If kv-bbb-pk1 is not present in the database, we will be positioned on
kv-bbb-pk0, and we will need to call it->Prev().
If we get an invalid iterator, we DO need to call SeekToLast().
RocksDB calls:
Seek(...);
if (!it->Valid())
it->SeekToLast();
else
{
if (!using_full_key ||
!(kd->covers_key(...) || kd->cmp_full_keys(...))
it->Prev();
}
if (it->Valid() && kd->covers_key(..))
return record.
== HA_READ_AFTER_KEY, forward CF ==
This is finding min(key) such that key > lookup_key.
Suppose lookup_key = kv-bbb
( kv )-aaa-pk
# ( kv )-bbb
( kv )-bbb-pk1 <--- Seek("kv-bbb") will put us here. We need to
( kv )-bbb-pk2 get to the value that is next after 'bbb'.
( kv )-bbb-pk3
( kv )-bbb-pk4
( kv )-bbb-pk5
( kv )-ccc-pkN <-- That is, we need to be here.
However, we don't know that the next value is kv-ccc. Instead, we seek to the
first value that strictly greater than 'kv-bbb'. It is Successor(kv-bbb).
It doesn't matter if we're using a full extended key or not.
RocksDB calls:
Seek(Successor(kv-bbb));
if (it->Valid() && kd->covers_key(it.key()))
return record;
Note that the code is the same as with HA_READ_KEY_OR_NEXT, except that
we seek to Successor($lookup_key) instead of $lookup_key itself.
== HA_READ_AFTER_KEY, backward CF ==
Suppose, the lookup key is 'kv-bbb':
(kv+1)-xxx-pk
( kv )-ccc-pk7
( kv )-ccc-pk6 <-- We need to be here.
# Successor(kv-bbb) <-- We get here when we call Seek(Successor(kv-bbb))
( kv )-bbb-pk5 and we will need to call Prev() (*)
( kv )-bbb-pk4
( kv )-bbb-pk3
( kv )-bbb-pk2
( kv )-bbb-pk1
# ( kv )-bbb <-- We would get here if we called Seek(kv-bbb).
( kv )-aaa-pk
(*) - unless Successor(kv-bbb)=(kv-ccc), and Seek(kv-ccc) hits the row. In
that case, we won't need to call Prev().
RocksDB calls:
Seek(Successor(kv-bbb));
if (!it->Valid())
{
/*
We may get EOF if rows with 'kv-bbb' (below the Successor... line in the
diagram) do not exist. This doesn't mean that rows with values kv-ccc
do not exist.
*/
it->SeekToLast();
}
else
{
if (!using_full_key ||
!kd->value_matches_prefix(...))
{
it->Prev();
}
}
if (it->Valid() && kd->covers_key(...))
return record.
Note that the code is the same as with HA_READ_KEY_OR_NEXT, except that
we seek to Successor($lookup_key) instead of $lookup_key itself.
== HA_READ_BEFORE_KEY, forward CF ==
This is finding max(key) such that key < lookup_tuple.
Suppose, lookup_tuple=kv-bbb.
( kv )-aaa-pk1
( kv )-aaa-pk2
( kv )-aaa-pk3 <-- Need to be here.
# ( kv )-bbb
( kv )-bbb-pk4 <-- Seek("kv-bbb") will put us here.
( kv )-bbb-pk5
( kv )-bbb-pk6
1. Seek(kv-bbb) will put us at kv-bbb-pk4 (or return an invalid iterator
if kv-bbb-pk4 and subsequent rows do not exist in the db).
2. We will need to call Prev() to get to the record before.
(if there is no record before kv-bbb, then we can't find a record).
It doesn't matter if we're using a full extended key or not.
RocksDB calls:
it->Seek(kv-bbb);
if (it->Valid())
it->Prev();
else
it->SeekToLast();
if (it->Valid() && kd->covers_key(...))
return record;
== HA_READ_BEFORE_KEY, backward CF ==
This is finding max(key) such that key < lookup_tuple.
Suppose, lookup_tuple=kv-bbb, a prefix of the full key.
( kv )-bbb-pk6
( kv )-bbb-pk5
( kv )-bbb-pk4
# ( kv )-bbb
( kv )-aaa-pk3 <-- Need to be here, and Seek("kv-bbb") will put us here
( kv )-aaa-pk2
( kv )-aaa-pk1
If the lookup tuple is a full key (e.g. kv-bbb-pk4), and the key is present in
the database, the iterator will be positioned on the key. We will need to call
Next() to get the next key.
RocksDB calls:
it->Seek(kv-bbb);
if (it->Valid() && using_full_key &&
kd->value_matches_prefix(...))
{
/* We are using full key and we've hit an exact match */
it->Next();
}
if (it->Valid() && kd->covers_key(...))
return record;
== HA_READ_PREFIX_LAST, forward CF ==
Find the last record with the specified index prefix lookup_tuple.
Suppose, lookup_tuple='kv-bbb'
( kv )-aaa-pk2
( kv )-aaa-pk3
# ( kv )-bbb
( kv )-bbb-pk4
( kv )-bbb-pk5
( kv )-bbb-pk6
( kv )-bbb-pk7 <--- Need to be here.
# ( kv )-ccc
( kv )-ccc-pk8 <-- Seek(Successor(kv-bbb)) will get us here. will need
( kv )-ccc-pk9 to call Prev().
RocksDB calls:
Seek(Successor(kv-bbb));
if (!it->Valid())
it->SeekToLast();
else
it->Prev();
if (it->Valid() && kd->covers_key(...))
{
if (!cmp_full_keys(lookup_tuple)) // not needed in _OR_PREV
{
// the record's prefix matches lookup_tuple.
return record;
}
}
== HA_READ_PREFIX_LAST, backward CF ==
Suppose, lookup_tuple='kv-bbb'
( kv )-ccc-pk9
( kv )-ccc-pk8
# ( kv )-ccc <-- 2. Seek(Successor(kv-bbb)) will point here
and it will fall down to the next row.
( kv )-bbb-pk7 <--- 1. Need to be here.
( kv )-bbb-pk6
( kv )-bbb-pk5
( kv )-bbb-pk4
# ( kv )-bbb
( kv )-aaa-pk3
( kv )-aaa-pk2
RocksDB calls:
it->Seek(Successor(kv-bbb));
if (using_full_key && it->Valid() && !cmp_full_keys(Sucessor(lookup_key)))
it->Next();
if (it->Valid() && kd->covers_key(..))
{
if (!cmp_full_keys(...)) // not needed in _OR_PREV
{
// the record's prefix matches lookup_tuple.
return record;
}
}
== HA_READ_PREFIX_LAST_OR_PREV, forward or backward CF ==
This is just like HA_READ_PREFIX_LAST but we don't need to check that the key
we've got is in the search prefix. (search for "not needed in _OR_PREV" above)