17.2 Statistics

DB统计信息提供随时间的累积统计信息。 它的功能与DB属性和perf和IO Stats上下文不同: 统计信息为历史积累统计信息,而DB属性报告数据库的当前状态; DB statistics提供了所有操作的聚合视图,而perf和IO stats上下文(https://github.com/facebook/rocksdb/wiki/Perf-Context-and-IO-Stats-Context)允许我们查看单个操作的内部。

使用

函数CreateDBStatistics()创建一个统计对象。

下面是一个例子,它传递给一个DB:

  1. Options options;
  2. options.statistics = rocksdb::CreateDBStatistics();

从技术上讲,您可以创建一个统计对象并传递给多个DBs。然后,statistics对象将包含所有这些DBs的聚合值。 注意,有些统计信息是未定义的,没有跨多个DBs的有意义的信息。其中一个统计数据是”rocksdb.sequence.number”。

高级用户可以实现自己的统计类。有关详细信息,请参阅最后一节。

统计级别和性能成本

统计的开销通常很小,但不可忽略。我们通常观察到5%-10%的开销。

统计数据使用原子整数(原子增量)实现。此外,度量时间持续时间的stats需要调用get当前时间。 原子增量和计时函数都引入了开销,这在不同的平台上是不同的。

我们有五个层次的统计,kexcepthistogramortimer, kexcepttimer, kexceptdetailedtimer, kExceptTimeForMutex和kAll。(kexcepthistogramortimer和kexcepttimer 只在6.1版本之后可用)

  • kAll: 收集所有统计信息,包括测量互斥锁操作的持续时间。如果在平台上运行时间是昂贵的,那么它可以将可伸缩性降低到更多的线程,尤其是写线程。
  • kExceptTimeForMutex: 收集除需要在互斥锁中获取时间的计数器之外的所有统计信息。rocksdb.db.mutex.wait。微计数器不测量。通过测量计数器,我们调用DB互斥量中的定时函数。如果计时功能较慢,则会显著降低写吞吐量。
  • kExceptDetailedTimers: 收集除互斥锁内时间和压缩时间外的所有统计信息。
  • kExceptTimers: 不包括所有计时统计。
  • kExceptHistogramOrTimers: 不包括所有计时统计,以及直方图。直方图比纯计数器统计更昂贵,因为它需要查找特定的桶并维护min/max/count/std,等等。这是最轻量级的级别。

访问统计

统计类型

有两种类型的统计,ticker 和 histogram直方图。

ticker类型由64位无符号整数表示。该值从不减少或重置。Ticker统计数据用于测量计数器(例如 “rocksdb.block.cache.hit”,累积字节(例如 “rocksdb.bytes.written”或”time”(例如: “rocksdb.l0.slowdown.micros”)。

直方图类型度量一个stat在所有操作中的分布。大多数直方图表示DB操作持续时间的分布。采取”rocksdb.db.get.micros” 例如,我们度量每个Get()操作花费的时间,并计算它们的分布。

打印可读字符串

我们可以通过调用ToString()获得所有计数器的可读字符串。

定期在信息日志中转储统计信息

统计信息会自动转储到信息日志中,用于周期性间隔 options.stats_dump_period_sec。 在5.18版本之前,它只有在压缩之后才被转储,因此,如果数据库长时间不提供任何写入服务,那么尽管有options.stats_dump_period_sec,统计数据可能不会被转储。

以编程方式访问数据

我们还可以直接从statistics对象访问特定的stat。ticker类型的列表可以在enum Tickers中找到。通过为ticker类型调用statistics.getTickerCount(),我们可以检索该值。 类似地,可以使用enum直方图调用statistics.histogram.data()或statistics.getHistogramString()来查询单个直方图stat。

统计数据的时间间隔

所有的统计数据都是自数据库开放以来累积的。如果需要在时间间隔的基础上监视或报告该值,可以定期检查该值,并通过取当前值与前一个值之间的差来计算时间间隔值。