Use prefix_same_as_start to avoid iteration in FindNextUserEntryInternal. (#1102)

This avoids excessive iteration in tombstone fields.
main
Peter Mattis 9 years ago committed by Islam AbdelRahman
parent 992a8f83b7
commit c6c770a1ac
  1. 53
      db/db_iter.cc
  2. 4
      db/prefix_test.cc

@ -201,8 +201,8 @@ class DBIter: public Iterator {
bool FindValueForCurrentKeyUsingSeek(); bool FindValueForCurrentKeyUsingSeek();
void FindPrevUserKey(); void FindPrevUserKey();
void FindNextUserKey(); void FindNextUserKey();
inline void FindNextUserEntry(bool skipping); inline void FindNextUserEntry(bool skipping, bool prefix_check);
void FindNextUserEntryInternal(bool skipping); void FindNextUserEntryInternal(bool skipping, bool prefix_check);
bool ParseKey(ParsedInternalKey* key); bool ParseKey(ParsedInternalKey* key);
void MergeValuesNewToOld(); void MergeValuesNewToOld();
@ -234,8 +234,9 @@ class DBIter: public Iterator {
uint64_t max_skip_; uint64_t max_skip_;
uint64_t version_number_; uint64_t version_number_;
const Slice* iterate_upper_bound_; const Slice* iterate_upper_bound_;
IterKey prefix_start_; IterKey prefix_start_buf_;
bool prefix_same_as_start_; Slice prefix_start_key_;
const bool prefix_same_as_start_;
// Means that we will pin all data blocks we read as long the Iterator // Means that we will pin all data blocks we read as long the Iterator
// is not deleted, will be true if ReadOptions::pin_data is true // is not deleted, will be true if ReadOptions::pin_data is true
const bool pin_thru_lifetime_; const bool pin_thru_lifetime_;
@ -289,12 +290,7 @@ void DBIter::Next() {
valid_ = false; valid_ = false;
return; return;
} }
FindNextUserEntry(true /* skipping the current user key */); FindNextUserEntry(true /* skipping the current user key */, prefix_same_as_start_);
if (valid_ && prefix_extractor_ && prefix_same_as_start_ &&
prefix_extractor_->Transform(saved_key_.GetKey())
.compare(prefix_start_.GetKey()) != 0) {
valid_ = false;
}
if (statistics_ != nullptr && valid_) { if (statistics_ != nullptr && valid_) {
local_stats_.next_found_count_++; local_stats_.next_found_count_++;
local_stats_.bytes_read_ += (key().size() + value().size()); local_stats_.bytes_read_ += (key().size() + value().size());
@ -309,13 +305,18 @@ void DBIter::Next() {
// //
// NOTE: In between, saved_key_ can point to a user key that has // NOTE: In between, saved_key_ can point to a user key that has
// a delete marker // a delete marker
inline void DBIter::FindNextUserEntry(bool skipping) { //
// The prefix_check parameter controls whether we check the iterated
// keys against the prefix of the seeked key. Set to false when
// performing a seek without a key (e.g. SeekToFirst). Set to
// prefix_same_as_start_ for other iterations.
inline void DBIter::FindNextUserEntry(bool skipping, bool prefix_check) {
PERF_TIMER_GUARD(find_next_user_entry_time); PERF_TIMER_GUARD(find_next_user_entry_time);
FindNextUserEntryInternal(skipping); FindNextUserEntryInternal(skipping, prefix_check);
} }
// Actual implementation of DBIter::FindNextUserEntry() // Actual implementation of DBIter::FindNextUserEntry()
void DBIter::FindNextUserEntryInternal(bool skipping) { void DBIter::FindNextUserEntryInternal(bool skipping, bool prefix_check) {
// Loop until we hit an acceptable entry to yield // Loop until we hit an acceptable entry to yield
assert(iter_->Valid()); assert(iter_->Valid());
assert(direction_ == kForward); assert(direction_ == kForward);
@ -330,6 +331,11 @@ void DBIter::FindNextUserEntryInternal(bool skipping) {
break; break;
} }
if (prefix_extractor_ && prefix_check &&
prefix_extractor_->Transform(ikey.user_key).compare(prefix_start_key_) != 0) {
break;
}
if (ikey.sequence <= sequence_) { if (ikey.sequence <= sequence_) {
if (skipping && if (skipping &&
user_comparator_->Compare(ikey.user_key, saved_key_.GetKey()) <= 0) { user_comparator_->Compare(ikey.user_key, saved_key_.GetKey()) <= 0) {
@ -476,7 +482,7 @@ void DBIter::Prev() {
} }
if (valid_ && prefix_extractor_ && prefix_same_as_start_ && if (valid_ && prefix_extractor_ && prefix_same_as_start_ &&
prefix_extractor_->Transform(saved_key_.GetKey()) prefix_extractor_->Transform(saved_key_.GetKey())
.compare(prefix_start_.GetKey()) != 0) { .compare(prefix_start_key_) != 0) {
valid_ = false; valid_ = false;
} }
} }
@ -772,9 +778,15 @@ void DBIter::Seek(const Slice& target) {
RecordTick(statistics_, NUMBER_DB_SEEK); RecordTick(statistics_, NUMBER_DB_SEEK);
if (iter_->Valid()) { if (iter_->Valid()) {
if (prefix_extractor_ && prefix_same_as_start_) {
prefix_start_key_ = prefix_extractor_->Transform(target);
}
direction_ = kForward; direction_ = kForward;
ClearSavedValue(); ClearSavedValue();
FindNextUserEntry(false /* not skipping */); FindNextUserEntry(false /* not skipping */, prefix_same_as_start_);
if (!valid_) {
prefix_start_key_.clear();
}
if (statistics_ != nullptr) { if (statistics_ != nullptr) {
if (valid_) { if (valid_) {
RecordTick(statistics_, NUMBER_DB_SEEK_FOUND); RecordTick(statistics_, NUMBER_DB_SEEK_FOUND);
@ -785,7 +797,8 @@ void DBIter::Seek(const Slice& target) {
valid_ = false; valid_ = false;
} }
if (valid_ && prefix_extractor_ && prefix_same_as_start_) { if (valid_ && prefix_extractor_ && prefix_same_as_start_) {
prefix_start_.SetKey(prefix_extractor_->Transform(target)); prefix_start_buf_.SetKey(prefix_start_key_);
prefix_start_key_ = prefix_start_buf_.GetKey();
} }
} }
@ -805,7 +818,7 @@ void DBIter::SeekToFirst() {
RecordTick(statistics_, NUMBER_DB_SEEK); RecordTick(statistics_, NUMBER_DB_SEEK);
if (iter_->Valid()) { if (iter_->Valid()) {
FindNextUserEntry(false /* not skipping */); FindNextUserEntry(false /* not skipping */, false /* no prefix check */);
if (statistics_ != nullptr) { if (statistics_ != nullptr) {
if (valid_) { if (valid_) {
RecordTick(statistics_, NUMBER_DB_SEEK_FOUND); RecordTick(statistics_, NUMBER_DB_SEEK_FOUND);
@ -816,7 +829,8 @@ void DBIter::SeekToFirst() {
valid_ = false; valid_ = false;
} }
if (valid_ && prefix_extractor_ && prefix_same_as_start_) { if (valid_ && prefix_extractor_ && prefix_same_as_start_) {
prefix_start_.SetKey(prefix_extractor_->Transform(saved_key_.GetKey())); prefix_start_buf_.SetKey(prefix_extractor_->Transform(saved_key_.GetKey()));
prefix_start_key_ = prefix_start_buf_.GetKey();
} }
} }
@ -864,7 +878,8 @@ void DBIter::SeekToLast() {
} }
} }
if (valid_ && prefix_extractor_ && prefix_same_as_start_) { if (valid_ && prefix_extractor_ && prefix_same_as_start_) {
prefix_start_.SetKey(prefix_extractor_->Transform(saved_key_.GetKey())); prefix_start_buf_.SetKey(prefix_extractor_->Transform(saved_key_.GetKey()));
prefix_start_key_ = prefix_start_buf_.GetKey();
} }
} }

@ -446,6 +446,10 @@ TEST_F(PrefixTest, PrefixValid) {
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Valid()); ASSERT_FALSE(iter->Valid());
ASSERT_EQ(kNotFoundResult, Get(db.get(), read_options, 12346, 8)); ASSERT_EQ(kNotFoundResult, Get(db.get(), read_options, 12346, 8));
// Verify seeking past the prefix won't return a result.
SeekIterator(iter.get(), 12345, 10);
ASSERT_TRUE(!iter->Valid());
} }
} }
} }

Loading…
Cancel
Save