现在的位置: 首页 > 综合 > 正文

leveldb 查找过程

2013年04月07日 ⁄ 综合 ⁄ 共 3037字 ⁄ 字号 评论关闭

         我们先看下面代码

1074   {
1075     mutex_.Unlock();
1076     // First look in the memtable, then in the immutable memtable (if any).
1077     LookupKey lkey(key, snapshot);
1078     if (mem->Get(lkey, value, &s)) {
1079       // Done
1080     } else if (imm != NULL && imm->Get(lkey, value, &s)) {
1081       // Done
1082     } else {
1083       s = current->Get(options, lkey, value, &stats);
1084       have_stat_update = true;
1085     }
1086     mutex_.Lock();
1087   }

从上面的代码可以看出,查询过程首先是在memTable不查找,如果找不到并且存在 immutable memtable,那么就在这里查找, 实在找不到,最后去ssTable中查找。 
        我们知道memTable 和immutable memTable都是使用跳表的结构实现,他们的查找就是在跳表中查找,这里就不介绍,我们主要来介绍下ssTable查找过程。 

version_set.cc

Status Version::Get(const ReadOptions& options,
                    const LookupKey& k,
                    std::string* value,
                    GetStats* stats) {
  Slice ikey = k.internal_key();
  Slice user_key = k.user_key();
  const Comparator* ucmp = vset_->icmp_.user_comparator();
  Status s;

  stats->seek_file = NULL;
  stats->seek_file_level = -1;
  FileMetaData* last_file_read = NULL;
  int last_file_read_level = -1;

  // We can search level-by-level since entries never hop across
  // levels.  Therefore we are guaranteed that if we find data
  // in an smaller level, later levels are irrelevant.
  std::vector<FileMetaData*> tmp;
  FileMetaData* tmp2;
  //从最底层开始,往上查找
  for (int level = 0; level < config::kNumLevels; level++) {
    size_t num_files = files_[level].size();
    if (num_files == 0) continue;

    // Get the list of files to search in this level
    FileMetaData* const* files = &files_[level][0];
    if (level == 0) {
      // Level-0 files may overlap each other.  Find all files that
      // overlap user_key and process them in order from newest to oldest.
      tmp.reserve(num_files);
      for (uint32_t i = 0; i < num_files; i++) {
        FileMetaData* f = files[i];
        if (ucmp->Compare(user_key, f->smallest.user_key()) >= 0 &&
            ucmp->Compare(user_key, f->largest.user_key()) <= 0) {
          tmp.push_back(f);
        }
      }
      if (tmp.empty()) continue;

      std::sort(tmp.begin(), tmp.end(), NewestFirst);
      files = &tmp[0];
      num_files = tmp.size();
    } else {
      // Binary search to find earliest index whose largest key >= ikey.
      uint32_t index = FindFile(vset_->icmp_, files_[level], ikey);
      if (index >= num_files) {
        files = NULL;
        num_files = 0;
      } else {
        tmp2 = files[index];
        if (ucmp->Compare(user_key, tmp2->smallest.user_key()) < 0) {
          // All of "tmp2" is past any data for user_key
          files = NULL;
          num_files = 0;
        } else {
          files = &tmp2;
          num_files = 1;
        }
      }
    }

    for (uint32_t i = 0; i < num_files; ++i) {
      if (last_file_read != NULL && stats->seek_file == NULL) {
        // We have had more than one seek for this read.  Charge the 1st file.
        stats->seek_file = last_file_read;
        stats->seek_file_level = last_file_read_level;
      }

      FileMetaData* f = files[i];
      last_file_read = f;
      last_file_read_level = level;

      Saver saver;
      saver.state = kNotFound;
      saver.ucmp = ucmp;
      saver.user_key = user_key;
      saver.value = value;
      s = vset_->table_cache_->Get(options, f->number, f->file_size,
                                   ikey, &saver, SaveValue);
      if (!s.ok()) {
        return s;
      }
      switch (saver.state) {
        case kNotFound:
          break;      // Keep searching in other files
        case kFound:
          return s;
        case kDeleted:
          s = Status::NotFound(Slice());  // Use empty error message for speed
          return s;
        case kCorrupt:
          s = Status::Corruption("corrupted key for ", user_key);
          return s;
      }
    }
  }

  return Status::NotFound(Slice());  // Use an empty error message for speed
}

整个过程从level 0开始,逐层往上查找,找到就返回。 每层查找又分为查找候选文件和对候选文件内查找。查找候选文件除了level 0 是全部检测以后,其它都采用二分查找就可以。 文件内部查找调用

vset_->table_cache_->Get 实现。 最后对查到的结果进行类型判断(found, no found , corrupt)

最后我们再来看看这个table_cache中Get的实现

vset_->table_cache_->Get 实现。 最后对查到的结果进行类型判断(found, no found , corrupt)

抱歉!评论已关闭.