1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
|
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 <--- SeekForPrev("kv-bbb") will put us here on the previous
record.
# ( kv )-bbb <--- "kv-bbb" doesn't exist in the database, but it would be
( kv )-aaa-pk here.
Even when (kv)-bbb-pk1 is the last record in the CF, SeekForPrev() will find the
last record before "kv-bbb", so it already takes care of this case for us.
RocksDB calls:
it->SeekForPrev(kv);
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(..))
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 <--- Seek("kv-bbb") will put us here on the previous record.
# ( kv )-bbb <--- "kv-bbb" doesn't exist in the database, but it would be
here.
( kv )-aaa-pk
Even when (kv)-bbb-pk1 is the last record in the CF, SeekForPrev() will find the
last record before "kv-bbb", so it already takes care of this case for us.
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 < -- SeekForPrev(kv-bbb-pk1)
( kv )-bbb-pk0
Then, SeekForPrev(kv-bbb-pk1) may position us exactly at the tuple we need.
Even If kv-bbb-pk1 is not present in the database, we will be positioned on
kv-bbb-pk2 no matter whether kv-bbb-pk2 is the last key or not.
RocksDB calls:
SeekForPrev(...);
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(...))
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 get here when we call Seek(Successor(kv-bbb))
# Successor(kv-bbb)
( kv )-bbb-pk5
( kv )-bbb-pk4
( kv )-bbb-pk3
( kv )-bbb-pk2
( kv )-bbb-pk1
# ( kv )-bbb <-- We would get here if we called SeekForPrev(kv-bbb).
( kv )-aaa-pk
RocksDB calls:
SeekForPrev(Successor(kv-bbb));
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 <-- SeekForPrev("kv-bbb") will put us here.
# ( kv )-bbb
( kv )-bbb-pk4
( kv )-bbb-pk5
( kv )-bbb-pk6
If the lookup tuple is a full key (e.g. kv-bbb-pk3), and the key is present in
the database, the iterator will be positioned on the key. We will need to call
Prev() to get the next key.
RocksDB calls:
it->SeekForPrev(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->Prev();
}
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 <--- SeekForPrev(Successor(kv-bbb)) will get us here
# ( kv )-ccc
( kv )-ccc-pk8
( kv )-ccc-pk9
RocksDB calls:
SeekForPrev(Successor(kv-bbb));
if (using_full_key && it->Valid() && !cmp_full_keys(Sucessor(lookup_key)))
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)
|