mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-02-19 03:04:27 -05:00
feat(cli): add RocksDB table stats to reth db stats command (#21221)
Co-authored-by: joshieDo <93316087+joshieDo@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
238433e146
commit
37b5db0d47
@@ -11,7 +11,10 @@ use reth_db_common::DbTool;
|
||||
use reth_fs_util as fs;
|
||||
use reth_node_builder::{NodePrimitives, NodeTypesWithDB, NodeTypesWithDBAdapter};
|
||||
use reth_node_core::dirs::{ChainPath, DataDirPath};
|
||||
use reth_provider::providers::{ProviderNodeTypes, StaticFileProvider};
|
||||
use reth_provider::{
|
||||
providers::{ProviderNodeTypes, StaticFileProvider},
|
||||
RocksDBProviderFactory,
|
||||
};
|
||||
use reth_static_file_types::SegmentRangeInclusive;
|
||||
use std::{sync::Arc, time::Duration};
|
||||
|
||||
@@ -61,6 +64,11 @@ impl Command {
|
||||
let db_stats_table = self.db_stats_table(tool)?;
|
||||
println!("{db_stats_table}");
|
||||
|
||||
println!("\n");
|
||||
|
||||
let rocksdb_stats_table = self.rocksdb_stats_table(tool);
|
||||
println!("{rocksdb_stats_table}");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -148,6 +156,45 @@ impl Command {
|
||||
Ok(table)
|
||||
}
|
||||
|
||||
fn rocksdb_stats_table<N: NodeTypesWithDB>(&self, tool: &DbTool<N>) -> ComfyTable {
|
||||
let mut table = ComfyTable::new();
|
||||
table.load_preset(comfy_table::presets::ASCII_MARKDOWN);
|
||||
table.set_header(["RocksDB Table Name", "# Entries", "Total Size", "Pending Compaction"]);
|
||||
|
||||
let stats = tool.provider_factory.rocksdb_provider().table_stats();
|
||||
let mut total_size: u64 = 0;
|
||||
let mut total_pending: u64 = 0;
|
||||
|
||||
for stat in &stats {
|
||||
total_size += stat.estimated_size_bytes;
|
||||
total_pending += stat.pending_compaction_bytes;
|
||||
let mut row = Row::new();
|
||||
row.add_cell(Cell::new(&stat.name))
|
||||
.add_cell(Cell::new(stat.estimated_num_keys))
|
||||
.add_cell(Cell::new(human_bytes(stat.estimated_size_bytes as f64)))
|
||||
.add_cell(Cell::new(human_bytes(stat.pending_compaction_bytes as f64)));
|
||||
table.add_row(row);
|
||||
}
|
||||
|
||||
if !stats.is_empty() {
|
||||
let max_widths = table.column_max_content_widths();
|
||||
let mut separator = Row::new();
|
||||
for width in max_widths {
|
||||
separator.add_cell(Cell::new("-".repeat(width as usize)));
|
||||
}
|
||||
table.add_row(separator);
|
||||
|
||||
let mut row = Row::new();
|
||||
row.add_cell(Cell::new("RocksDB Total"))
|
||||
.add_cell(Cell::new(""))
|
||||
.add_cell(Cell::new(human_bytes(total_size as f64)))
|
||||
.add_cell(Cell::new(human_bytes(total_pending as f64)));
|
||||
table.add_row(row);
|
||||
}
|
||||
|
||||
table
|
||||
}
|
||||
|
||||
fn static_files_stats_table<N: NodePrimitives>(
|
||||
&self,
|
||||
data_dir: ChainPath<DataDirPath>,
|
||||
|
||||
@@ -38,7 +38,9 @@ pub use consistent::ConsistentProvider;
|
||||
#[cfg_attr(not(all(unix, feature = "rocksdb")), path = "rocksdb_stub.rs")]
|
||||
pub(crate) mod rocksdb;
|
||||
|
||||
pub use rocksdb::{RocksDBBatch, RocksDBBuilder, RocksDBProvider, RocksDBRawIter, RocksTx};
|
||||
pub use rocksdb::{
|
||||
RocksDBBatch, RocksDBBuilder, RocksDBProvider, RocksDBRawIter, RocksDBTableStats, RocksTx,
|
||||
};
|
||||
|
||||
/// Helper trait to bound [`NodeTypes`] so that combined with database they satisfy
|
||||
/// [`ProviderNodeTypes`].
|
||||
|
||||
@@ -5,4 +5,6 @@ mod metrics;
|
||||
mod provider;
|
||||
|
||||
pub(crate) use provider::{PendingRocksDBBatches, RocksDBWriteCtx};
|
||||
pub use provider::{RocksDBBatch, RocksDBBuilder, RocksDBProvider, RocksDBRawIter, RocksTx};
|
||||
pub use provider::{
|
||||
RocksDBBatch, RocksDBBuilder, RocksDBProvider, RocksDBRawIter, RocksDBTableStats, RocksTx,
|
||||
};
|
||||
|
||||
@@ -38,6 +38,19 @@ use tracing::instrument;
|
||||
/// Pending `RocksDB` batches type alias.
|
||||
pub(crate) type PendingRocksDBBatches = Arc<Mutex<Vec<WriteBatchWithTransaction<true>>>>;
|
||||
|
||||
/// Statistics for a single `RocksDB` table (column family).
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RocksDBTableStats {
|
||||
/// Name of the table/column family.
|
||||
pub name: String,
|
||||
/// Estimated number of keys in the table.
|
||||
pub estimated_num_keys: u64,
|
||||
/// Estimated size of live data in bytes (SST files + memtables).
|
||||
pub estimated_size_bytes: u64,
|
||||
/// Estimated bytes pending compaction (reclaimable space).
|
||||
pub pending_compaction_bytes: u64,
|
||||
}
|
||||
|
||||
/// Context for `RocksDB` block writes.
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct RocksDBWriteCtx {
|
||||
@@ -405,6 +418,69 @@ impl RocksDBProviderInner {
|
||||
Self::ReadOnly { db, .. } => RocksDBIterEnum::ReadOnly(db.iterator_cf(cf, mode)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns statistics for all column families in the database.
|
||||
fn table_stats(&self) -> Vec<RocksDBTableStats> {
|
||||
let cf_names = [
|
||||
tables::TransactionHashNumbers::NAME,
|
||||
tables::AccountsHistory::NAME,
|
||||
tables::StoragesHistory::NAME,
|
||||
];
|
||||
|
||||
let mut stats = Vec::new();
|
||||
|
||||
macro_rules! collect_stats {
|
||||
($db:expr) => {
|
||||
for cf_name in cf_names {
|
||||
if let Some(cf) = $db.cf_handle(cf_name) {
|
||||
let estimated_num_keys = $db
|
||||
.property_int_value_cf(cf, rocksdb::properties::ESTIMATE_NUM_KEYS)
|
||||
.ok()
|
||||
.flatten()
|
||||
.unwrap_or(0);
|
||||
|
||||
// SST files size (on-disk) + memtable size (in-memory)
|
||||
let sst_size = $db
|
||||
.property_int_value_cf(cf, rocksdb::properties::LIVE_SST_FILES_SIZE)
|
||||
.ok()
|
||||
.flatten()
|
||||
.unwrap_or(0);
|
||||
|
||||
let memtable_size = $db
|
||||
.property_int_value_cf(cf, rocksdb::properties::SIZE_ALL_MEM_TABLES)
|
||||
.ok()
|
||||
.flatten()
|
||||
.unwrap_or(0);
|
||||
|
||||
let estimated_size_bytes = sst_size + memtable_size;
|
||||
|
||||
let pending_compaction_bytes = $db
|
||||
.property_int_value_cf(
|
||||
cf,
|
||||
rocksdb::properties::ESTIMATE_PENDING_COMPACTION_BYTES,
|
||||
)
|
||||
.ok()
|
||||
.flatten()
|
||||
.unwrap_or(0);
|
||||
|
||||
stats.push(RocksDBTableStats {
|
||||
name: cf_name.to_string(),
|
||||
estimated_num_keys,
|
||||
estimated_size_bytes,
|
||||
pending_compaction_bytes,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
match self {
|
||||
Self::ReadWrite { db, .. } => collect_stats!(db),
|
||||
Self::ReadOnly { db, .. } => collect_stats!(db),
|
||||
}
|
||||
|
||||
stats
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for RocksDBProviderInner {
|
||||
@@ -666,6 +742,13 @@ impl RocksDBProvider {
|
||||
Ok(RocksDBIter { inner: iter, _marker: std::marker::PhantomData })
|
||||
}
|
||||
|
||||
/// Returns statistics for all column families in the database.
|
||||
///
|
||||
/// Returns a vector of (`table_name`, `estimated_keys`, `estimated_size_bytes`) tuples.
|
||||
pub fn table_stats(&self) -> Vec<RocksDBTableStats> {
|
||||
self.0.table_stats()
|
||||
}
|
||||
|
||||
/// Creates a raw iterator over all entries in the specified table.
|
||||
///
|
||||
/// Returns raw `(key_bytes, value_bytes)` pairs without decoding.
|
||||
|
||||
@@ -14,6 +14,19 @@ use std::{path::Path, sync::Arc};
|
||||
/// Pending `RocksDB` batches type alias (stub - uses unit type).
|
||||
pub(crate) type PendingRocksDBBatches = Arc<Mutex<Vec<()>>>;
|
||||
|
||||
/// Statistics for a single `RocksDB` table (column family) - stub.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RocksDBTableStats {
|
||||
/// Name of the table/column family.
|
||||
pub name: String,
|
||||
/// Estimated number of keys in the table.
|
||||
pub estimated_num_keys: u64,
|
||||
/// Estimated size of live data in bytes (SST files + memtables).
|
||||
pub estimated_size_bytes: u64,
|
||||
/// Estimated bytes pending compaction (reclaimable space).
|
||||
pub pending_compaction_bytes: u64,
|
||||
}
|
||||
|
||||
/// Context for `RocksDB` block writes (stub).
|
||||
#[derive(Debug, Clone)]
|
||||
#[allow(dead_code)]
|
||||
@@ -56,6 +69,13 @@ impl RocksDBProvider {
|
||||
) -> ProviderResult<Option<BlockNumber>> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Returns statistics for all column families in the database (stub implementation).
|
||||
///
|
||||
/// Returns an empty vector since there is no `RocksDB` when the feature is disabled.
|
||||
pub const fn table_stats(&self) -> Vec<RocksDBTableStats> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
/// A stub batch writer for `RocksDB`.
|
||||
|
||||
Reference in New Issue
Block a user