aggregated-table-properties with GetMapProperty (#7779)
Summary: So that we can more easily get aggregate live table data such as total filter, index, and data sizes. Also adds ldb support for getting properties Also fixed some missing/inaccurate related comments in db.h For example: $ ./ldb --db=testdb get_property rocksdb.aggregated-table-properties rocksdb.aggregated-table-properties.data_size: 102871 rocksdb.aggregated-table-properties.filter_size: 0 rocksdb.aggregated-table-properties.index_partitions: 0 rocksdb.aggregated-table-properties.index_size: 2232 rocksdb.aggregated-table-properties.num_data_blocks: 100 rocksdb.aggregated-table-properties.num_deletions: 0 rocksdb.aggregated-table-properties.num_entries: 15000 rocksdb.aggregated-table-properties.num_merge_operands: 0 rocksdb.aggregated-table-properties.num_range_deletions: 0 rocksdb.aggregated-table-properties.raw_key_size: 288890 rocksdb.aggregated-table-properties.raw_value_size: 198890 rocksdb.aggregated-table-properties.top_level_index_size: 0 $ ./ldb --db=testdb get_property rocksdb.aggregated-table-properties-at-level1 rocksdb.aggregated-table-properties-at-level1.data_size: 80909 rocksdb.aggregated-table-properties-at-level1.filter_size: 0 rocksdb.aggregated-table-properties-at-level1.index_partitions: 0 rocksdb.aggregated-table-properties-at-level1.index_size: 1787 rocksdb.aggregated-table-properties-at-level1.num_data_blocks: 81 rocksdb.aggregated-table-properties-at-level1.num_deletions: 0 rocksdb.aggregated-table-properties-at-level1.num_entries: 12466 rocksdb.aggregated-table-properties-at-level1.num_merge_operands: 0 rocksdb.aggregated-table-properties-at-level1.num_range_deletions: 0 rocksdb.aggregated-table-properties-at-level1.raw_key_size: 238210 rocksdb.aggregated-table-properties-at-level1.raw_value_size: 163414 rocksdb.aggregated-table-properties-at-level1.top_level_index_size: 0 $ Pull Request resolved: https://github.com/facebook/rocksdb/pull/7779 Test Plan: Added a test to ldb_test.py Reviewed By: jay-zhuang Differential Revision: D25653103 Pulled By: pdillinger fbshipit-source-id: 2905469a08a64dd6b5510cbd7be2e64d3234d6d3
This commit is contained in:
parent
fbce7a3808
commit
4d1ac19e3d
@ -15,6 +15,7 @@
|
||||
|
||||
### New Features
|
||||
* User defined timestamp feature supports `CompactRange` and `GetApproximateSizes`.
|
||||
* Support getting aggregated table properties (kAggregatedTableProperties and kAggregatedTablePropertiesAtLevel) with DB::GetMapProperty, for easier access to the data in a structured format.
|
||||
* Experimental option BlockBasedTableOptions::optimize_filters_for_memory now works with experimental Ribbon filter (as well as Bloom filter).
|
||||
|
||||
### Public API Change
|
||||
|
@ -378,10 +378,11 @@ const std::unordered_map<std::string, DBPropertyInfo>
|
||||
{false, &InternalStats::HandleSsTables, nullptr, nullptr, nullptr}},
|
||||
{DB::Properties::kAggregatedTableProperties,
|
||||
{false, &InternalStats::HandleAggregatedTableProperties, nullptr,
|
||||
nullptr, nullptr}},
|
||||
&InternalStats::HandleAggregatedTablePropertiesMap, nullptr}},
|
||||
{DB::Properties::kAggregatedTablePropertiesAtLevel,
|
||||
{false, &InternalStats::HandleAggregatedTablePropertiesAtLevel,
|
||||
nullptr, nullptr, nullptr}},
|
||||
nullptr, &InternalStats::HandleAggregatedTablePropertiesAtLevelMap,
|
||||
nullptr}},
|
||||
{DB::Properties::kNumImmutableMemTable,
|
||||
{false, nullptr, &InternalStats::HandleNumImmutableMemTable, nullptr,
|
||||
nullptr}},
|
||||
@ -510,11 +511,12 @@ bool InternalStats::GetStringProperty(const DBPropertyInfo& property_info,
|
||||
}
|
||||
|
||||
bool InternalStats::GetMapProperty(const DBPropertyInfo& property_info,
|
||||
const Slice& /*property*/,
|
||||
const Slice& property,
|
||||
std::map<std::string, std::string>* value) {
|
||||
assert(value != nullptr);
|
||||
assert(property_info.handle_map != nullptr);
|
||||
return (this->*(property_info.handle_map))(value);
|
||||
Slice arg = GetPropertyNameAndArg(property).second;
|
||||
return (this->*(property_info.handle_map))(value, arg);
|
||||
}
|
||||
|
||||
bool InternalStats::GetIntProperty(const DBPropertyInfo& property_info,
|
||||
@ -590,7 +592,7 @@ bool InternalStats::HandleStats(std::string* value, Slice suffix) {
|
||||
}
|
||||
|
||||
bool InternalStats::HandleCFMapStats(
|
||||
std::map<std::string, std::string>* cf_stats) {
|
||||
std::map<std::string, std::string>* cf_stats, Slice /*suffix*/) {
|
||||
DumpCFMapStats(cf_stats);
|
||||
return true;
|
||||
}
|
||||
@ -634,7 +636,27 @@ bool InternalStats::HandleAggregatedTableProperties(std::string* value,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleAggregatedTablePropertiesAtLevel(std::string* value,
|
||||
static std::map<std::string, std::string> MapUint64ValuesToString(
|
||||
const std::map<std::string, uint64_t>& from) {
|
||||
std::map<std::string, std::string> to;
|
||||
for (const auto& e : from) {
|
||||
to[e.first] = ToString(e.second);
|
||||
}
|
||||
return to;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleAggregatedTablePropertiesMap(
|
||||
std::map<std::string, std::string>* values, Slice /*suffix*/) {
|
||||
std::shared_ptr<const TableProperties> tp;
|
||||
auto s = cfd_->current()->GetAggregatedTableProperties(&tp);
|
||||
if (!s.ok()) {
|
||||
return false;
|
||||
}
|
||||
*values = MapUint64ValuesToString(tp->GetAggregatablePropertiesAsMap());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleAggregatedTablePropertiesAtLevel(std::string* values,
|
||||
Slice suffix) {
|
||||
uint64_t level;
|
||||
bool ok = ConsumeDecimalNumber(&suffix, &level) && suffix.empty();
|
||||
@ -647,7 +669,24 @@ bool InternalStats::HandleAggregatedTablePropertiesAtLevel(std::string* value,
|
||||
if (!s.ok()) {
|
||||
return false;
|
||||
}
|
||||
*value = tp->ToString();
|
||||
*values = tp->ToString();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleAggregatedTablePropertiesAtLevelMap(
|
||||
std::map<std::string, std::string>* values, Slice suffix) {
|
||||
uint64_t level;
|
||||
bool ok = ConsumeDecimalNumber(&suffix, &level) && suffix.empty();
|
||||
if (!ok || static_cast<int>(level) >= number_levels_) {
|
||||
return false;
|
||||
}
|
||||
std::shared_ptr<const TableProperties> tp;
|
||||
auto s = cfd_->current()->GetAggregatedTableProperties(
|
||||
&tp, static_cast<int>(level));
|
||||
if (!s.ok()) {
|
||||
return false;
|
||||
}
|
||||
*values = MapUint64ValuesToString(tp->GetAggregatablePropertiesAsMap());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,9 @@ struct DBPropertyInfo {
|
||||
Version* version);
|
||||
|
||||
// @param props Map of general properties to populate
|
||||
bool (InternalStats::*handle_map)(std::map<std::string, std::string>* props);
|
||||
// @param suffix Argument portion of the property. (see handle_string)
|
||||
bool (InternalStats::*handle_map)(std::map<std::string, std::string>* props,
|
||||
Slice suffix);
|
||||
|
||||
// handle the string type properties rely on DBImpl methods
|
||||
// @param value Value-result argument for storing the property's string value
|
||||
@ -525,7 +527,8 @@ class InternalStats {
|
||||
bool HandleCompressionRatioAtLevelPrefix(std::string* value, Slice suffix);
|
||||
bool HandleLevelStats(std::string* value, Slice suffix);
|
||||
bool HandleStats(std::string* value, Slice suffix);
|
||||
bool HandleCFMapStats(std::map<std::string, std::string>* compaction_stats);
|
||||
bool HandleCFMapStats(std::map<std::string, std::string>* compaction_stats,
|
||||
Slice suffix);
|
||||
bool HandleCFStats(std::string* value, Slice suffix);
|
||||
bool HandleCFStatsNoFileHistogram(std::string* value, Slice suffix);
|
||||
bool HandleCFFileHistogram(std::string* value, Slice suffix);
|
||||
@ -533,6 +536,10 @@ class InternalStats {
|
||||
bool HandleSsTables(std::string* value, Slice suffix);
|
||||
bool HandleAggregatedTableProperties(std::string* value, Slice suffix);
|
||||
bool HandleAggregatedTablePropertiesAtLevel(std::string* value, Slice suffix);
|
||||
bool HandleAggregatedTablePropertiesMap(
|
||||
std::map<std::string, std::string>* values, Slice suffix);
|
||||
bool HandleAggregatedTablePropertiesAtLevelMap(
|
||||
std::map<std::string, std::string>* values, Slice suffix);
|
||||
bool HandleNumImmutableMemTable(uint64_t* value, DBImpl* db,
|
||||
Version* version);
|
||||
bool HandleNumImmutableMemTableFlushed(uint64_t* value, DBImpl* db,
|
||||
|
@ -713,7 +713,9 @@ class DB {
|
||||
virtual void ReleaseSnapshot(const Snapshot* snapshot) = 0;
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
// Contains all valid property arguments for GetProperty().
|
||||
// Contains all valid property arguments for GetProperty() or
|
||||
// GetMapProperty(). Each is a "string" property for retrieval with
|
||||
// GetProperty() unless noted as a "map" property, for GetMapProperty().
|
||||
//
|
||||
// NOTE: Property names cannot end in numbers since those are interpreted as
|
||||
// arguments, e.g., see kNumFilesAtLevelPrefix.
|
||||
@ -738,19 +740,14 @@ class DB {
|
||||
// SST files.
|
||||
static const std::string kSSTables;
|
||||
|
||||
// "rocksdb.cfstats" - Both of "rocksdb.cfstats-no-file-histogram" and
|
||||
// "rocksdb.cf-file-histogram" together. See below for description
|
||||
// of the two.
|
||||
// "rocksdb.cfstats" - Raw data from "rocksdb.cfstats-no-file-histogram"
|
||||
// and "rocksdb.cf-file-histogram" as a "map" property.
|
||||
static const std::string kCFStats;
|
||||
|
||||
// "rocksdb.cfstats-no-file-histogram" - returns a multi-line string with
|
||||
// general columm family stats per-level over db's lifetime ("L<n>"),
|
||||
// aggregated over db's lifetime ("Sum"), and aggregated over the
|
||||
// interval since the last retrieval ("Int").
|
||||
// It could also be used to return the stats in the format of the map.
|
||||
// In this case there will a pair of string to array of double for
|
||||
// each level as well as for "Sum". "Int" stats will not be affected
|
||||
// when this form of stats are retrieved.
|
||||
static const std::string kCFStatsNoFileHistogram;
|
||||
|
||||
// "rocksdb.cf-file-histogram" - print out how many file reads to every
|
||||
@ -891,8 +888,10 @@ class DB {
|
||||
// based.
|
||||
static const std::string kEstimatePendingCompactionBytes;
|
||||
|
||||
// "rocksdb.aggregated-table-properties" - returns a string representation
|
||||
// of the aggregated table properties of the target column family.
|
||||
// "rocksdb.aggregated-table-properties" - returns a string or map
|
||||
// representation of the aggregated table properties of the target
|
||||
// column family. Only properties that make sense for aggregation
|
||||
// are included.
|
||||
static const std::string kAggregatedTableProperties;
|
||||
|
||||
// "rocksdb.aggregated-table-properties-at-level<N>", same as the previous
|
||||
@ -930,15 +929,19 @@ class DB {
|
||||
};
|
||||
#endif /* ROCKSDB_LITE */
|
||||
|
||||
// DB implementations can export properties about their state via this method.
|
||||
// If "property" is a valid property understood by this DB implementation (see
|
||||
// Properties struct above for valid options), fills "*value" with its current
|
||||
// value and returns true. Otherwise, returns false.
|
||||
// DB implementations export properties about their state via this method.
|
||||
// If "property" is a valid "string" property understood by this DB
|
||||
// implementation (see Properties struct above for valid options), fills
|
||||
// "*value" with its current value and returns true. Otherwise, returns
|
||||
// false.
|
||||
virtual bool GetProperty(ColumnFamilyHandle* column_family,
|
||||
const Slice& property, std::string* value) = 0;
|
||||
virtual bool GetProperty(const Slice& property, std::string* value) {
|
||||
return GetProperty(DefaultColumnFamily(), property, value);
|
||||
}
|
||||
|
||||
// Like GetProperty but for valid "map" properties. (Some properties can be
|
||||
// accessed as either "string" properties or "map" properties.)
|
||||
virtual bool GetMapProperty(ColumnFamilyHandle* column_family,
|
||||
const Slice& property,
|
||||
std::map<std::string, std::string>* value) = 0;
|
||||
|
@ -258,6 +258,11 @@ struct TableProperties {
|
||||
// Aggregate the numerical member variables of the specified
|
||||
// TableProperties.
|
||||
void Add(const TableProperties& tp);
|
||||
|
||||
// Subset of properties that make sense when added together
|
||||
// between tables. Keys match field names in this class instead
|
||||
// of using full property names.
|
||||
std::map<std::string, uint64_t> GetAggregatablePropertiesAsMap() const;
|
||||
};
|
||||
|
||||
// Extra properties
|
||||
|
@ -193,6 +193,24 @@ void TableProperties::Add(const TableProperties& tp) {
|
||||
num_range_deletions += tp.num_range_deletions;
|
||||
}
|
||||
|
||||
std::map<std::string, uint64_t>
|
||||
TableProperties::GetAggregatablePropertiesAsMap() const {
|
||||
std::map<std::string, uint64_t> rv;
|
||||
rv["data_size"] = data_size;
|
||||
rv["index_size"] = index_size;
|
||||
rv["index_partitions"] = index_partitions;
|
||||
rv["top_level_index_size"] = top_level_index_size;
|
||||
rv["filter_size"] = filter_size;
|
||||
rv["raw_key_size"] = raw_key_size;
|
||||
rv["raw_value_size"] = raw_value_size;
|
||||
rv["num_data_blocks"] = num_data_blocks;
|
||||
rv["num_entries"] = num_entries;
|
||||
rv["num_deletions"] = num_deletions;
|
||||
rv["num_merge_operands"] = num_merge_operands;
|
||||
rv["num_range_deletions"] = num_range_deletions;
|
||||
return rv;
|
||||
}
|
||||
|
||||
const std::string TablePropertiesNames::kDbId = "rocksdb.creating.db.identity";
|
||||
const std::string TablePropertiesNames::kDbSessionId =
|
||||
"rocksdb.creating.session.identity";
|
||||
|
@ -227,6 +227,10 @@ LDBCommand* LDBCommand::SelectCommand(const ParsedParams& parsed_params) {
|
||||
return new FileChecksumDumpCommand(parsed_params.cmd_params,
|
||||
parsed_params.option_map,
|
||||
parsed_params.flags);
|
||||
} else if (parsed_params.cmd == GetPropertyCommand::Name()) {
|
||||
return new GetPropertyCommand(parsed_params.cmd_params,
|
||||
parsed_params.option_map,
|
||||
parsed_params.flags);
|
||||
} else if (parsed_params.cmd == ListColumnFamiliesCommand::Name()) {
|
||||
return new ListColumnFamiliesCommand(parsed_params.cmd_params,
|
||||
parsed_params.option_map,
|
||||
@ -1259,6 +1263,58 @@ void FileChecksumDumpCommand::DoCommand() {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void GetPropertyCommand::Help(std::string& ret) {
|
||||
ret.append(" ");
|
||||
ret.append(GetPropertyCommand::Name());
|
||||
ret.append(" <property_name>");
|
||||
ret.append("\n");
|
||||
}
|
||||
|
||||
GetPropertyCommand::GetPropertyCommand(
|
||||
const std::vector<std::string>& params,
|
||||
const std::map<std::string, std::string>& options,
|
||||
const std::vector<std::string>& flags)
|
||||
: LDBCommand(options, flags, true, BuildCmdLineOptions({})) {
|
||||
if (params.size() != 1) {
|
||||
exec_state_ =
|
||||
LDBCommandExecuteResult::Failed("property name must be specified");
|
||||
} else {
|
||||
property_ = params[0];
|
||||
}
|
||||
}
|
||||
|
||||
void GetPropertyCommand::DoCommand() {
|
||||
if (!db_) {
|
||||
assert(GetExecuteState().IsFailed());
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> value_map;
|
||||
std::string value;
|
||||
|
||||
// Rather than having different ldb command for map properties vs. string
|
||||
// properties, we simply try Map property first. (This order only chosen
|
||||
// because I prefer the map-style output for
|
||||
// "rocksdb.aggregated-table-properties".)
|
||||
if (db_->GetMapProperty(GetCfHandle(), property_, &value_map)) {
|
||||
if (value_map.empty()) {
|
||||
fprintf(stdout, "%s: <empty map>\n", property_.c_str());
|
||||
} else {
|
||||
for (auto& e : value_map) {
|
||||
fprintf(stdout, "%s.%s: %s\n", property_.c_str(), e.first.c_str(),
|
||||
e.second.c_str());
|
||||
}
|
||||
}
|
||||
} else if (db_->GetProperty(GetCfHandle(), property_, &value)) {
|
||||
fprintf(stdout, "%s: %s\n", property_.c_str(), value.c_str());
|
||||
} else {
|
||||
exec_state_ =
|
||||
LDBCommandExecuteResult::Failed("failed to get property: " + property_);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void ListColumnFamiliesCommand::Help(std::string& ret) {
|
||||
ret.append(" ");
|
||||
ret.append(ListColumnFamiliesCommand::Name());
|
||||
|
@ -190,6 +190,21 @@ class FileChecksumDumpCommand : public LDBCommand {
|
||||
static const std::string ARG_PATH;
|
||||
};
|
||||
|
||||
class GetPropertyCommand : public LDBCommand {
|
||||
public:
|
||||
static std::string Name() { return "get_property"; }
|
||||
|
||||
GetPropertyCommand(const std::vector<std::string>& params,
|
||||
const std::map<std::string, std::string>& options,
|
||||
const std::vector<std::string>& flags);
|
||||
|
||||
static void Help(std::string& ret);
|
||||
void DoCommand() override;
|
||||
|
||||
private:
|
||||
std::string property_;
|
||||
};
|
||||
|
||||
class ListColumnFamiliesCommand : public LDBCommand {
|
||||
public:
|
||||
static std::string Name() { return "list_column_families"; }
|
||||
|
@ -473,6 +473,27 @@ class LDBTestCase(unittest.TestCase):
|
||||
expected_pattern, unexpected=False,
|
||||
isPattern=True)
|
||||
|
||||
def testGetProperty(self):
|
||||
print("Running testGetProperty...")
|
||||
dbPath = os.path.join(self.TMP_DIR, self.DB_NAME)
|
||||
self.assertRunOK("put 1 1 --create_if_missing", "OK")
|
||||
self.assertRunOK("put 2 2", "OK")
|
||||
# A "string" property
|
||||
cmd = "--db=%s get_property rocksdb.estimate-num-keys"
|
||||
self.assertRunOKFull(cmd % dbPath,
|
||||
"rocksdb.estimate-num-keys: 2")
|
||||
# A "map" property
|
||||
# FIXME: why doesn't this pick up two entries?
|
||||
cmd = "--db=%s get_property rocksdb.aggregated-table-properties"
|
||||
part = "rocksdb.aggregated-table-properties.num_entries: "
|
||||
expected_pattern = re.compile(part)
|
||||
self.assertRunOKFull(cmd % dbPath,
|
||||
expected_pattern, unexpected=False,
|
||||
isPattern=True)
|
||||
# An invalid property
|
||||
cmd = "--db=%s get_property rocksdb.this-property-does-not-exist"
|
||||
self.assertRunFAILFull(cmd % dbPath)
|
||||
|
||||
def testSSTDump(self):
|
||||
print("Running testSSTDump...")
|
||||
|
||||
|
@ -87,6 +87,7 @@ void LDBCommandRunner::PrintHelp(const LDBOptions& ldb_options,
|
||||
DBLoaderCommand::Help(ret);
|
||||
ManifestDumpCommand::Help(ret);
|
||||
FileChecksumDumpCommand::Help(ret);
|
||||
GetPropertyCommand::Help(ret);
|
||||
ListColumnFamiliesCommand::Help(ret);
|
||||
CreateColumnFamilyCommand::Help(ret);
|
||||
DropColumnFamilyCommand::Help(ret);
|
||||
|
Loading…
Reference in New Issue
Block a user