01

Physical models for metrics, logs and traces

OpenTelemetry gives us a consistent way to receive metrics, logs and traces, which is valuable at the boundary of the platform. It does not follow that the three signals should be written into one generic table. They contain different kinds of repetition, carry different relationships and are normally read through very different access paths.

A PromQL query begins with metric names and label matchers before reading dense sequences of timestamped values. A LogQL query usually resolves a stream and then applies text or structured-field filters. A TraceQL query searches span attributes and durations, but it may also need to follow relationships between spans in the same trace. A layout that is convenient for one of those paths can create unnecessary reads for another.

PulsusDB treats the OpenTelemetry representation as the interchange format rather than the physical storage model. Each signal is transformed into a schema designed around the access patterns of its query language, while retaining the resource and attribute identity needed to correlate signals later.

02

Query-driven schema design

The ClickHouse® database stores columns independently, but a columnar engine still depends on a good schema, appropriate ordering keys and useful indexes. Those choices determine whether a query can discard most of the dataset early or has to inspect a much larger range before it finds the relevant rows.

For metrics, PulsusDB separates series identity and labels from the dense sample path. Label matchers can be resolved into fingerprints before the database reads timestamp and value columns. Logs retain stream identity and structured metadata, while word indexes can eliminate granules that cannot contain an indexable term. This does not turn arbitrary substring search into an indexed operation, so the planner still has to be honest about which filters require a scan of the selected streams.

Trace storage has another set of requirements. Individual spans need to be searchable by service, operation, status, duration and attributes, but useful trace queries also depend on trace and parent identifiers. Keeping those relationships available lets the query layer return a matching span set or reconstruct the relevant trace context without treating every query as a scan of complete trace documents.

03

Compression and read efficiency

Compression is often discussed as a capacity concern, but it also changes the amount of work required to answer a query. Fewer stored bytes mean fewer bytes read from local disks or object storage, fewer compressed blocks moving through memory and better use of CPU caches during vectorised execution.

Signal-aware schemas tend to improve compression because similar values are stored together and ordered in ways that expose their repetition. Metric timestamps can use delta-of-delta encoding, floating-point samples can use Gorilla encoding and repeated dimensions benefit from the regularity of a columnar layout. Logs and traces have different patterns, so they need different choices rather than inheriting codecs selected for metric samples.

The query compiler benefits from the same separation. It targets predictable tables and columns for each query language instead of reconstructing signal semantics from a generic event structure at runtime. The result is not a trade between storage efficiency and query speed. A well-designed physical model usually improves both because the database stores less data and reads less of it for the same investigation.

END OF NOTEDATA.MODEL / 002