Total SST files size DB Property

Summary: Add a new DB property that calculate the total size of files used by all RocksDB Versions

Test Plan: Unittests for the new property

Reviewers: igor, yhchiang, anthony, rven, kradhakrishnan, sdong

Reviewed By: sdong

Subscribers: dhruba

Differential Revision: https://reviews.facebook.net/D44799
This commit is contained in:
Islam AbdelRahman 2015-08-20 11:47:19 -07:00
parent b604d2562f
commit 027ca5b2cd
8 changed files with 215 additions and 0 deletions

View File

@ -478,6 +478,10 @@ uint64_t ColumnFamilyData::GetNumLiveVersions() const {
return VersionSet::GetNumLiveVersions(dummy_versions_); return VersionSet::GetNumLiveVersions(dummy_versions_);
} }
uint64_t ColumnFamilyData::GetTotalSstFilesSize() const {
return VersionSet::GetTotalSstFilesSize(dummy_versions_);
}
MemTable* ColumnFamilyData::ConstructNewMemtable( MemTable* ColumnFamilyData::ConstructNewMemtable(
const MutableCFOptions& mutable_cf_options, SequenceNumber earliest_seq) { const MutableCFOptions& mutable_cf_options, SequenceNumber earliest_seq) {
assert(current_ != nullptr); assert(current_ != nullptr);

View File

@ -226,6 +226,7 @@ class ColumnFamilyData {
Version* dummy_versions() { return dummy_versions_; } Version* dummy_versions() { return dummy_versions_; }
void SetCurrent(Version* current); void SetCurrent(Version* current);
uint64_t GetNumLiveVersions() const; // REQUIRE: DB mutex held uint64_t GetNumLiveVersions() const; // REQUIRE: DB mutex held
uint64_t GetTotalSstFilesSize() const; // REQUIRE: DB mutex held
void SetMemtable(MemTable* new_mem) { mem_ = new_mem; } void SetMemtable(MemTable* new_mem) { mem_ = new_mem; }
// See Memtable constructor for explanation of earliest_seq param. // See Memtable constructor for explanation of earliest_seq param.

View File

@ -8574,6 +8574,183 @@ TEST_F(DBTest, OpenDBWithInfiniteMaxOpenFiles) {
} }
} }
TEST_F(DBTest, GetTotalSstFilesSize) {
Options options = CurrentOptions();
options.disable_auto_compactions = true;
options.compression = kNoCompression;
DestroyAndReopen(options);
// Generate 5 files in L0
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 10; j++) {
std::string val = "val_file_" + ToString(i);
ASSERT_OK(Put(Key(j), val));
}
Flush();
}
ASSERT_EQ("5", FilesPerLevel(0));
std::vector<LiveFileMetaData> live_files_meta;
dbfull()->GetLiveFilesMetaData(&live_files_meta);
ASSERT_EQ(live_files_meta.size(), 5);
uint64_t single_file_size = live_files_meta[0].size;
uint64_t live_sst_files_size = 0;
uint64_t total_sst_files_size = 0;
for (const auto& file_meta : live_files_meta) {
live_sst_files_size += file_meta.size;
}
ASSERT_TRUE(dbfull()->GetIntProperty("rocksdb.total-sst-files-size",
&total_sst_files_size));
// Live SST files = 5
// Total SST files = 5
ASSERT_EQ(live_sst_files_size, 5 * single_file_size);
ASSERT_EQ(total_sst_files_size, 5 * single_file_size);
// hold current version
std::unique_ptr<Iterator> iter1(dbfull()->NewIterator(ReadOptions()));
// Compact 5 files into 1 file in L0
ASSERT_OK(dbfull()->CompactRange(CompactRangeOptions(), nullptr, nullptr));
ASSERT_EQ("0,1", FilesPerLevel(0));
live_files_meta.clear();
dbfull()->GetLiveFilesMetaData(&live_files_meta);
ASSERT_EQ(live_files_meta.size(), 1);
live_sst_files_size = 0;
total_sst_files_size = 0;
for (const auto& file_meta : live_files_meta) {
live_sst_files_size += file_meta.size;
}
ASSERT_TRUE(dbfull()->GetIntProperty("rocksdb.total-sst-files-size",
&total_sst_files_size));
// Live SST files = 1 (compacted file)
// Total SST files = 6 (5 original files + compacted file)
ASSERT_EQ(live_sst_files_size, 1 * single_file_size);
ASSERT_EQ(total_sst_files_size, 6 * single_file_size);
// hold current version
std::unique_ptr<Iterator> iter2(dbfull()->NewIterator(ReadOptions()));
// Delete all keys and compact, this will delete all live files
for (int i = 0; i < 10; i++) {
ASSERT_OK(Delete(Key(i)));
}
Flush();
ASSERT_OK(dbfull()->CompactRange(CompactRangeOptions(), nullptr, nullptr));
ASSERT_EQ("", FilesPerLevel(0));
live_files_meta.clear();
dbfull()->GetLiveFilesMetaData(&live_files_meta);
ASSERT_EQ(live_files_meta.size(), 0);
ASSERT_TRUE(dbfull()->GetIntProperty("rocksdb.total-sst-files-size",
&total_sst_files_size));
// Live SST files = 0
// Total SST files = 6 (5 original files + compacted file)
ASSERT_EQ(total_sst_files_size, 6 * single_file_size);
iter1.reset();
ASSERT_TRUE(dbfull()->GetIntProperty("rocksdb.total-sst-files-size",
&total_sst_files_size));
// Live SST files = 0
// Total SST files = 1 (compacted file)
ASSERT_EQ(total_sst_files_size, 1 * single_file_size);
iter2.reset();
ASSERT_TRUE(dbfull()->GetIntProperty("rocksdb.total-sst-files-size",
&total_sst_files_size));
// Live SST files = 0
// Total SST files = 0
ASSERT_EQ(total_sst_files_size, 0);
}
TEST_F(DBTest, GetTotalSstFilesSizeVersionsFilesShared) {
Options options = CurrentOptions();
options.disable_auto_compactions = true;
options.compression = kNoCompression;
DestroyAndReopen(options);
// Generate 5 files in L0
for (int i = 0; i < 5; i++) {
ASSERT_OK(Put(Key(i), "val"));
Flush();
}
ASSERT_EQ("5", FilesPerLevel(0));
std::vector<LiveFileMetaData> live_files_meta;
dbfull()->GetLiveFilesMetaData(&live_files_meta);
ASSERT_EQ(live_files_meta.size(), 5);
uint64_t single_file_size = live_files_meta[0].size;
uint64_t live_sst_files_size = 0;
uint64_t total_sst_files_size = 0;
for (const auto& file_meta : live_files_meta) {
live_sst_files_size += file_meta.size;
}
ASSERT_TRUE(dbfull()->GetIntProperty("rocksdb.total-sst-files-size",
&total_sst_files_size));
// Live SST files = 5
// Total SST files = 5
ASSERT_EQ(live_sst_files_size, 5 * single_file_size);
ASSERT_EQ(total_sst_files_size, 5 * single_file_size);
// hold current version
std::unique_ptr<Iterator> iter1(dbfull()->NewIterator(ReadOptions()));
// Compaction will do trivial move from L0 to L1
ASSERT_OK(dbfull()->CompactRange(CompactRangeOptions(), nullptr, nullptr));
ASSERT_EQ("0,5", FilesPerLevel(0));
live_files_meta.clear();
dbfull()->GetLiveFilesMetaData(&live_files_meta);
ASSERT_EQ(live_files_meta.size(), 5);
live_sst_files_size = 0;
total_sst_files_size = 0;
for (const auto& file_meta : live_files_meta) {
live_sst_files_size += file_meta.size;
}
ASSERT_TRUE(dbfull()->GetIntProperty("rocksdb.total-sst-files-size",
&total_sst_files_size));
// Live SST files = 5
// Total SST files = 5 (used in 2 version)
ASSERT_EQ(live_sst_files_size, 5 * single_file_size);
ASSERT_EQ(total_sst_files_size, 5 * single_file_size);
// hold current version
std::unique_ptr<Iterator> iter2(dbfull()->NewIterator(ReadOptions()));
// Delete all keys and compact, this will delete all live files
for (int i = 0; i < 5; i++) {
ASSERT_OK(Delete(Key(i)));
}
Flush();
ASSERT_OK(dbfull()->CompactRange(CompactRangeOptions(), nullptr, nullptr));
ASSERT_EQ("", FilesPerLevel(0));
live_files_meta.clear();
dbfull()->GetLiveFilesMetaData(&live_files_meta);
ASSERT_EQ(live_files_meta.size(), 0);
ASSERT_TRUE(dbfull()->GetIntProperty("rocksdb.total-sst-files-size",
&total_sst_files_size));
// Live SST files = 0
// Total SST files = 5 (used in 2 version)
ASSERT_EQ(total_sst_files_size, 5 * single_file_size);
iter1.reset();
iter2.reset();
ASSERT_TRUE(dbfull()->GetIntProperty("rocksdb.total-sst-files-size",
&total_sst_files_size));
// Live SST files = 0
// Total SST files = 0
ASSERT_EQ(total_sst_files_size, 0);
}
INSTANTIATE_TEST_CASE_P(DBTestWithParam, DBTestWithParam, INSTANTIATE_TEST_CASE_P(DBTestWithParam, DBTestWithParam,
::testing::Values(1, 4)); ::testing::Values(1, 4));

View File

@ -122,6 +122,7 @@ static const std::string oldest_snapshot_time = "oldest-snapshot-time";
static const std::string num_live_versions = "num-live-versions"; static const std::string num_live_versions = "num-live-versions";
static const std::string estimate_live_data_size = "estimate-live-data-size"; static const std::string estimate_live_data_size = "estimate-live-data-size";
static const std::string base_level = "base-level"; static const std::string base_level = "base-level";
static const std::string total_sst_files_size = "total-sst-files-size";
const std::string DB::Properties::kNumFilesAtLevelPrefix = const std::string DB::Properties::kNumFilesAtLevelPrefix =
rocksdb_prefix + num_files_at_level_prefix; rocksdb_prefix + num_files_at_level_prefix;
@ -165,6 +166,8 @@ const std::string DB::Properties::kNumLiveVersions =
rocksdb_prefix + num_live_versions; rocksdb_prefix + num_live_versions;
const std::string DB::Properties::kEstimateLiveDataSize = const std::string DB::Properties::kEstimateLiveDataSize =
rocksdb_prefix + estimate_live_data_size; rocksdb_prefix + estimate_live_data_size;
const std::string DB::Properties::kTotalSstFilesSize =
rocksdb_prefix + total_sst_files_size;
DBPropertyType GetPropertyType(const Slice& property, bool* is_int_property, DBPropertyType GetPropertyType(const Slice& property, bool* is_int_property,
bool* need_out_of_mutex) { bool* need_out_of_mutex) {
@ -236,6 +239,8 @@ DBPropertyType GetPropertyType(const Slice& property, bool* is_int_property,
return kEstimateLiveDataSize; return kEstimateLiveDataSize;
} else if (in == base_level) { } else if (in == base_level) {
return kBaseLevel; return kBaseLevel;
} else if (in == total_sst_files_size) {
return kTotalSstFilesSize;
} }
return kUnknown; return kUnknown;
} }
@ -401,6 +406,9 @@ bool InternalStats::GetIntProperty(DBPropertyType property_type,
case kBaseLevel: case kBaseLevel:
*value = vstorage->base_level(); *value = vstorage->base_level();
return true; return true;
case kTotalSstFilesSize:
*value = cfd_->GetTotalSstFilesSize();
return true;
default: default:
return false; return false;
} }

View File

@ -61,6 +61,7 @@ enum DBPropertyType : uint32_t {
kOldestSnapshotTime, // Unix timestamp of the first snapshot kOldestSnapshotTime, // Unix timestamp of the first snapshot
kNumLiveVersions, kNumLiveVersions,
kEstimateLiveDataSize, // Estimated amount of live data in bytes kEstimateLiveDataSize, // Estimated amount of live data in bytes
kTotalSstFilesSize, // Total size of all sst files.
kBaseLevel, // The level that L0 data is compacted to kBaseLevel, // The level that L0 data is compacted to
}; };

View File

@ -3239,4 +3239,22 @@ uint64_t VersionSet::GetNumLiveVersions(Version* dummy_versions) {
return count; return count;
} }
uint64_t VersionSet::GetTotalSstFilesSize(Version* dummy_versions) {
std::unordered_set<uint64_t> unique_files;
uint64_t total_files_size = 0;
for (Version* v = dummy_versions->next_; v != dummy_versions; v = v->next_) {
VersionStorageInfo* storage_info = v->storage_info();
for (int level = 0; level < storage_info->num_levels_; level++) {
for (const auto& file_meta : storage_info->LevelFiles(level)) {
if (unique_files.find(file_meta->fd.packed_number_and_path_id) ==
unique_files.end()) {
unique_files.insert(file_meta->fd.packed_number_and_path_id);
total_files_size += file_meta->fd.GetFileSize();
}
}
}
}
return total_files_size;
}
} // namespace rocksdb } // namespace rocksdb

View File

@ -651,6 +651,8 @@ class VersionSet {
static uint64_t GetNumLiveVersions(Version* dummy_versions); static uint64_t GetNumLiveVersions(Version* dummy_versions);
static uint64_t GetTotalSstFilesSize(Version* dummy_versions);
private: private:
struct ManifestWriter; struct ManifestWriter;

View File

@ -328,6 +328,8 @@ class DB {
// files are held from being deleted, by iterators or unfinished // files are held from being deleted, by iterators or unfinished
// compactions. // compactions.
// "rocksdb.estimate-live-data-size" // "rocksdb.estimate-live-data-size"
// "rocksdb.total-sst-files-size" - total size of all used sst files, this may
// slow down online queries if there are too many files.
#ifndef ROCKSDB_LITE #ifndef ROCKSDB_LITE
struct Properties { struct Properties {
static const std::string kNumFilesAtLevelPrefix; static const std::string kNumFilesAtLevelPrefix;
@ -353,6 +355,7 @@ class DB {
static const std::string kOldestSnapshotTime; static const std::string kOldestSnapshotTime;
static const std::string kNumLiveVersions; static const std::string kNumLiveVersions;
static const std::string kEstimateLiveDataSize; static const std::string kEstimateLiveDataSize;
static const std::string kTotalSstFilesSize;
}; };
#endif /* ROCKSDB_LITE */ #endif /* ROCKSDB_LITE */
@ -383,6 +386,7 @@ class DB {
// "rocksdb.oldest-snapshot-time" // "rocksdb.oldest-snapshot-time"
// "rocksdb.num-live-versions" // "rocksdb.num-live-versions"
// "rocksdb.estimate-live-data-size" // "rocksdb.estimate-live-data-size"
// "rocksdb.total-sst-files-size"
virtual bool GetIntProperty(ColumnFamilyHandle* column_family, virtual bool GetIntProperty(ColumnFamilyHandle* column_family,
const Slice& property, uint64_t* value) = 0; const Slice& property, uint64_t* value) = 0;
virtual bool GetIntProperty(const Slice& property, uint64_t* value) { virtual bool GetIntProperty(const Slice& property, uint64_t* value) {