Adding GetApproximateMemTableStats method

Summary:
Added method that returns approx num of entries as well as size for memtables.
Closes https://github.com/facebook/rocksdb/pull/1841

Differential Revision: D4511990

Pulled By: VitaliyLi

fbshipit-source-id: 9a4576e
This commit is contained in:
Vitaliy Liptchinsky 2017-02-06 14:42:38 -08:00 committed by Facebook Github Bot
parent 9fc23c55f2
commit 1aaa898cf1
10 changed files with 132 additions and 14 deletions

View File

@ -7,6 +7,7 @@
* Added new overloaded function GetApproximateSizes that allows to specify if memtable stats should be computed only without computing SST files' stats approximations. * Added new overloaded function GetApproximateSizes that allows to specify if memtable stats should be computed only without computing SST files' stats approximations.
* NewLRUCache() will determine number of shard bits automatically based on capacity, if the user doesn't pass one. This also impacts the default block cache when the user doesn't explict provide one. * NewLRUCache() will determine number of shard bits automatically based on capacity, if the user doesn't pass one. This also impacts the default block cache when the user doesn't explict provide one.
* Change the default of delayed slowdown value to 16MB/s and further increase the L0 stop condition to 36 files. * Change the default of delayed slowdown value to 16MB/s and further increase the L0 stop condition to 36 files.
* Added new function GetApproximateMemTableStats that approximates both number of records and size of memtables.
### Bug Fixes ### Bug Fixes
* Fix the bug that if 2PC is enabled, checkpoints may loss some recent transactions. * Fix the bug that if 2PC is enabled, checkpoints may loss some recent transactions.

View File

@ -5558,6 +5558,28 @@ ColumnFamilyHandle* DBImpl::GetColumnFamilyHandle(uint32_t column_family_id) {
return cf_memtables->GetColumnFamilyHandle(); return cf_memtables->GetColumnFamilyHandle();
} }
void DBImpl::GetApproximateMemTableStats(ColumnFamilyHandle* column_family,
const Range& range,
uint64_t* const count,
uint64_t* const size) {
ColumnFamilyHandleImpl* cfh =
reinterpret_cast<ColumnFamilyHandleImpl*>(column_family);
ColumnFamilyData* cfd = cfh->cfd();
SuperVersion* sv = GetAndRefSuperVersion(cfd);
// Convert user_key into a corresponding internal key.
InternalKey k1(range.start, kMaxSequenceNumber, kValueTypeForSeek);
InternalKey k2(range.limit, kMaxSequenceNumber, kValueTypeForSeek);
MemTable::MemTableStats memStats =
sv->mem->ApproximateStats(k1.Encode(), k2.Encode());
MemTable::MemTableStats immStats =
sv->imm->ApproximateStats(k1.Encode(), k2.Encode());
*count = memStats.count + immStats.count;
*size = memStats.size + immStats.size;
ReturnAndCleanupSuperVersion(cfd, sv);
}
void DBImpl::GetApproximateSizes(ColumnFamilyHandle* column_family, void DBImpl::GetApproximateSizes(ColumnFamilyHandle* column_family,
const Range* range, int n, uint64_t* sizes, const Range* range, int n, uint64_t* sizes,
uint8_t include_flags) { uint8_t include_flags) {
@ -5578,8 +5600,8 @@ void DBImpl::GetApproximateSizes(ColumnFamilyHandle* column_family,
sizes[i] += versions_->ApproximateSize(v, k1.Encode(), k2.Encode()); sizes[i] += versions_->ApproximateSize(v, k1.Encode(), k2.Encode());
} }
if (include_flags & DB::SizeApproximationFlags::INCLUDE_MEMTABLES) { if (include_flags & DB::SizeApproximationFlags::INCLUDE_MEMTABLES) {
sizes[i] += sv->mem->ApproximateSize(k1.Encode(), k2.Encode()); sizes[i] += sv->mem->ApproximateStats(k1.Encode(), k2.Encode()).size;
sizes[i] += sv->imm->ApproximateSize(k1.Encode(), k2.Encode()); sizes[i] += sv->imm->ApproximateStats(k1.Encode(), k2.Encode()).size;
} }
} }

View File

@ -140,6 +140,11 @@ class DBImpl : public DB {
const Range* range, int n, uint64_t* sizes, const Range* range, int n, uint64_t* sizes,
uint8_t include_flags uint8_t include_flags
= INCLUDE_FILES) override; = INCLUDE_FILES) override;
using DB::GetApproximateMemTableStats;
virtual void GetApproximateMemTableStats(ColumnFamilyHandle* column_family,
const Range& range,
uint64_t* const count,
uint64_t* const size) override;
using DB::CompactRange; using DB::CompactRange;
virtual Status CompactRange(const CompactRangeOptions& options, virtual Status CompactRange(const CompactRangeOptions& options,
ColumnFamilyHandle* column_family, ColumnFamilyHandle* column_family,

View File

@ -1497,6 +1497,59 @@ TEST_F(DBTest, ApproximateSizesMemTable) {
ASSERT_GT(size_without_mt, 6000); ASSERT_GT(size_without_mt, 6000);
} }
TEST_F(DBTest, GetApproximateMemTableStats) {
Options options = CurrentOptions();
options.write_buffer_size = 100000000;
options.compression = kNoCompression;
options.create_if_missing = true;
DestroyAndReopen(options);
const int N = 128;
Random rnd(301);
for (int i = 0; i < N; i++) {
ASSERT_OK(Put(Key(i), RandomString(&rnd, 1024)));
}
uint64_t count;
uint64_t size;
std::string start = Key(50);
std::string end = Key(60);
Range r(start, end);
db_->GetApproximateMemTableStats(r, &count, &size);
ASSERT_GT(count, 0);
ASSERT_LE(count, N);
ASSERT_GT(size, 6000);
ASSERT_LT(size, 204800);
start = Key(500);
end = Key(600);
r = Range(start, end);
db_->GetApproximateMemTableStats(r, &count, &size);
ASSERT_EQ(count, 0);
ASSERT_EQ(size, 0);
Flush();
start = Key(50);
end = Key(60);
r = Range(start, end);
db_->GetApproximateMemTableStats(r, &count, &size);
ASSERT_EQ(count, 0);
ASSERT_EQ(size, 0);
for (int i = 0; i < N; i++) {
ASSERT_OK(Put(Key(1000 + i), RandomString(&rnd, 1024)));
}
start = Key(100);
end = Key(1020);
r = Range(start, end);
db_->GetApproximateMemTableStats(r, &count, &size);
ASSERT_GT(count, 20);
ASSERT_GT(size, 6000);
}
TEST_F(DBTest, ApproximateSizes) { TEST_F(DBTest, ApproximateSizes) {
do { do {
Options options = CurrentOptions(); Options options = CurrentOptions();
@ -2821,6 +2874,14 @@ class ModelDB : public DB {
sizes[i] = 0; sizes[i] = 0;
} }
} }
using DB::GetApproximateMemTableStats;
virtual void GetApproximateMemTableStats(ColumnFamilyHandle* column_family,
const Range& range,
uint64_t* const count,
uint64_t* const size) override {
*count = 0;
*size = 0;
}
using DB::CompactRange; using DB::CompactRange;
virtual Status CompactRange(const CompactRangeOptions& options, virtual Status CompactRange(const CompactRangeOptions& options,
ColumnFamilyHandle* column_family, ColumnFamilyHandle* column_family,

View File

@ -390,16 +390,16 @@ port::RWMutex* MemTable::GetLock(const Slice& key) {
return &locks_[hash(key) % locks_.size()]; return &locks_[hash(key) % locks_.size()];
} }
uint64_t MemTable::ApproximateSize(const Slice& start_ikey, MemTable::MemTableStats MemTable::ApproximateStats(const Slice& start_ikey,
const Slice& end_ikey) { const Slice& end_ikey) {
uint64_t entry_count = table_->ApproximateNumEntries(start_ikey, end_ikey); uint64_t entry_count = table_->ApproximateNumEntries(start_ikey, end_ikey);
entry_count += range_del_table_->ApproximateNumEntries(start_ikey, end_ikey); entry_count += range_del_table_->ApproximateNumEntries(start_ikey, end_ikey);
if (entry_count == 0) { if (entry_count == 0) {
return 0; return {0, 0};
} }
uint64_t n = num_entries_.load(std::memory_order_relaxed); uint64_t n = num_entries_.load(std::memory_order_relaxed);
if (n == 0) { if (n == 0) {
return 0; return {0, 0};
} }
if (entry_count > n) { if (entry_count > n) {
// (range_del_)table_->ApproximateNumEntries() is just an estimate so it can // (range_del_)table_->ApproximateNumEntries() is just an estimate so it can
@ -408,7 +408,7 @@ uint64_t MemTable::ApproximateSize(const Slice& start_ikey,
entry_count = n; entry_count = n;
} }
uint64_t data_size = data_size_.load(std::memory_order_relaxed); uint64_t data_size = data_size_.load(std::memory_order_relaxed);
return entry_count * (data_size / n); return {entry_count * (data_size / n), entry_count};
} }
void MemTable::Add(SequenceNumber s, ValueType type, void MemTable::Add(SequenceNumber s, ValueType type,

View File

@ -326,7 +326,13 @@ class MemTable {
return table_->IsSnapshotSupported() && !moptions_.inplace_update_support; return table_->IsSnapshotSupported() && !moptions_.inplace_update_support;
} }
uint64_t ApproximateSize(const Slice& start_ikey, const Slice& end_ikey); struct MemTableStats {
uint64_t size;
uint64_t count;
};
MemTableStats ApproximateStats(const Slice& start_ikey,
const Slice& end_ikey);
// Get the lock associated for the key // Get the lock associated for the key
port::RWMutex* GetLock(const Slice& key); port::RWMutex* GetLock(const Slice& key);

View File

@ -190,13 +190,15 @@ uint64_t MemTableListVersion::GetTotalNumEntries() const {
return total_num; return total_num;
} }
uint64_t MemTableListVersion::ApproximateSize(const Slice& start_ikey, MemTable::MemTableStats MemTableListVersion::ApproximateStats(
const Slice& end_ikey) { const Slice& start_ikey, const Slice& end_ikey) {
uint64_t total_size = 0; MemTable::MemTableStats total_stats = {0, 0};
for (auto& m : memlist_) { for (auto& m : memlist_) {
total_size += m->ApproximateSize(start_ikey, end_ikey); auto mStats = m->ApproximateStats(start_ikey, end_ikey);
total_stats.size += mStats.size;
total_stats.count += mStats.count;
} }
return total_size; return total_stats;
} }
uint64_t MemTableListVersion::GetTotalNumDeletes() const { uint64_t MemTableListVersion::GetTotalNumDeletes() const {

View File

@ -95,7 +95,8 @@ class MemTableListVersion {
uint64_t GetTotalNumDeletes() const; uint64_t GetTotalNumDeletes() const;
uint64_t ApproximateSize(const Slice& start_ikey, const Slice& end_ikey); MemTable::MemTableStats ApproximateStats(const Slice& start_ikey,
const Slice& end_ikey);
// Returns the value of MemTable::GetEarliestSequenceNumber() on the most // Returns the value of MemTable::GetEarliestSequenceNumber() on the most
// recent MemTable in this list or kMaxSequenceNumber if the list is empty. // recent MemTable in this list or kMaxSequenceNumber if the list is empty.

View File

@ -616,6 +616,18 @@ class DB {
include_flags); include_flags);
} }
// The method is similar to GetApproximateSizes, except it
// returns approximate number of records in memtables.
virtual void GetApproximateMemTableStats(ColumnFamilyHandle* column_family,
const Range& range,
uint64_t* const count,
uint64_t* const size) = 0;
virtual void GetApproximateMemTableStats(const Range& range,
uint64_t* const count,
uint64_t* const size) {
GetApproximateMemTableStats(DefaultColumnFamily(), range, count, size);
}
// Deprecated versions of GetApproximateSizes // Deprecated versions of GetApproximateSizes
ROCKSDB_DEPRECATED_FUNC virtual void GetApproximateSizes( ROCKSDB_DEPRECATED_FUNC virtual void GetApproximateSizes(
const Range* range, int n, uint64_t* sizes, const Range* range, int n, uint64_t* sizes,

View File

@ -167,6 +167,14 @@ class StackableDB : public DB {
include_flags); include_flags);
} }
using DB::GetApproximateMemTableStats;
virtual void GetApproximateMemTableStats(ColumnFamilyHandle* column_family,
const Range& range,
uint64_t* const count,
uint64_t* const size) override {
return db_->GetApproximateMemTableStats(column_family, range, count, size);
}
using DB::CompactRange; using DB::CompactRange;
virtual Status CompactRange(const CompactRangeOptions& options, virtual Status CompactRange(const CompactRangeOptions& options,
ColumnFamilyHandle* column_family, ColumnFamilyHandle* column_family,