[PATCH] vinyl: don't move to next range if it doesn't match EQ search key

Vladimir Davydov vdavydov.dev at gmail.com
Wed Feb 28 12:14:32 MSK 2018


When iterating over a vinyl index, we move to the next range if the
minimal (in terms of the search criteria) statement among all sources
is outside the current range - see vy_read_iterator_next_key() and
vy_read_iterator_range_is_done(). This is OK for GE/GT/LE/LT, but for
EQ/REQ we should also make sure that the next range actually intersects
with the search key - if it doesn't, there's no point in iterating to
it. We used to have that check, but commit 5e414a73e93 ("vinyl: read
iterator: do not reopen all sources when range is changed") accidentally
removed it. As a result, unlimited EQ/REQ requests for partial keys read
runs of all ranges and therefore take much longer. This patch brings
this check back.
---
https://github.com/tarantool/tarantool/tree/vy-fix-read-iterator-perf-degradation

 src/box/vy_read_iterator.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/box/vy_read_iterator.c b/src/box/vy_read_iterator.c
index d08be9a0..1ba33ffe 100644
--- a/src/box/vy_read_iterator.c
+++ b/src/box/vy_read_iterator.c
@@ -131,6 +131,11 @@ vy_read_iterator_unpin_slices(struct vy_read_iterator *itr)
 /**
  * Return true if the current statement is outside the current
  * range and hence we should move to the next range.
+ *
+ * If we are looking for a match (EQ, REQ) and the search key
+ * doesn't intersect with the current range's boundary, the next
+ * range can't contain statements matching the search criteria
+ * and hence there's no point in iterating to it.
  */
 static bool
 vy_read_iterator_range_is_done(struct vy_read_iterator *itr)
@@ -142,12 +147,16 @@ vy_read_iterator_range_is_done(struct vy_read_iterator *itr)
 
 	if (dir > 0 && range->end != NULL &&
 	    (stmt == NULL || vy_tuple_compare_with_key(stmt,
-				range->end, cmp_def) >= 0))
+				range->end, cmp_def) >= 0) &&
+	    (itr->iterator_type != ITER_EQ ||
+	     vy_stmt_compare_with_key(itr->key, range->end, cmp_def) >= 0))
 		return true;
 
 	if (dir < 0 && range->begin != NULL &&
 	    (stmt == NULL || vy_tuple_compare_with_key(stmt,
-				range->begin, cmp_def) < 0))
+				range->begin, cmp_def) < 0) &&
+	    (itr->iterator_type != ITER_REQ ||
+	     vy_stmt_compare_with_key(itr->key, range->begin, cmp_def) <= 0))
 		return true;
 
 	return false;
-- 
2.11.0




More information about the Tarantool-patches mailing list