TimescaleDB
repository·main·Indexed 12 days ago
https://github.com/timescale/timescaledbA PostgreSQL extension for high-performance real-time analytics on time-series and event data. Features include hypertables, continuous aggregates, and optimized support for UUIDv7 in version 2.24+. Supports direct loading to columnstore via timescaledb.enable_direct_compress_copy and specialized time-series functions like time_bucket and to_uuidv7_boundary().
What's inside TimescaleDB
- Coccinelle is a static code analysis program used to detect defective programming patterns (such as use-after-free or resource leaks) in a codebase. It operates using a semantic patch language that resembles unified diff output. For advanced use cases, these semantic patches can inline Python or OCaml code.
Understand the FastLanes C library
mainFastLanes is a mostly header-only C library that implements bit-packing inspired by the FastLanes compression layout. It is designed as a building block for higher-level compression algorithms rather than a standalone compression tool.
Key characteristics:
- Purpose: Packs integers into a transposed format to allow efficient SIMD-based packing and unpacking.
- Implementation: Uses portable C and C macros to allow compilers to generate efficient SIMD code without relying on platform-specific intrinsics.
- Mechanism: Lays $N$ values across $S$ parallel lanes. Each lane stores $N/S$ values, dense-packed at $W$ bits per slot. The lanes are interleaved in memory to enable SIMD parallelism.
- Use Case: Ideal for packing odd bit-width integers (e.g., 5-bit integers) without wasting space or splitting integers across boundaries.
Multi-node support deprecation notice
mainMulti-node support in TimescaleDB has been deprecated. TimescaleDB 2.13 is the final version that includes multi-node support. In version 2.13, multi-node is compatible with PostgreSQL 13, 14, and 15. Future versions of TimescaleDB will no longer include multi-node functionality.Explore the TimescaleDB TSL Library components
mainThe TimescaleDB TSL library provides specialized implementations for time-series data management. Key functional areas include:
- Continuous Aggregates: Tools for incrementally refreshing materialized views over time-series data.
- Compression: Mechanisms for reducing the storage footprint of time-series data.
- Query optimization for time series: Specialized query nodes and logic designed to optimize time-series workloads.
Use the Vector ADT for dynamic storage
mainTheVectorADT is a dynamic implementation designed to store any type. It manages memory automatically, handling the growing and shrinking of memory allocations as elements are added or removed.Understand the ADT (Abstract Data Type) implementation pattern
mainTimescaleDB uses a specific pattern for Abstract Data Types (ADTs) to implement containers that can store any data type. Unlike many implementations that usevoidpointers, these ADTs use C macros. This approach is chosen to improve performance and provide better type safety, following standard PostgreSQL conventions.Implement Object-Oriented patterns in C
mainTimescaleDB recommends an OOP-like approach for modularity and code reuse.
Key patterns include:
- Struct Embedding for Inheritance: Place the base struct as the first member of the derived struct. This allows a pointer to the derived struct to be safely cast to a pointer to the base struct.
- Virtual Functions: Implement C++-style virtual functions using function pointers within structs. This is useful for module-specific initialization, cleanup, or overriding behavior in subclasses.
- Namespaced Methods: Non-static methods should take a pointer to the object as the first argument and be prefixed with the module name.
typedef struct Shape { int color; void (*draw)(Shape *, Canvas *); // Virtual function pointer } Shape; typedef struct Circle { Shape shape; // Base class as first member for upcasting float diameter; } Circle; void shape_draw(Shape *shape) { Canvas *c = canvas_open(); shape->draw(shape, c); canvas_close(c); } void circle_draw(Shape *shape, Canvas *canvas) { Circle *circle = (Circle *) shape; // Downcasting /* draw circle logic */ } Circle blue_circle = { .shape = { .color = BLUE, .draw = circle_draw, }, .diameter = 10.1, };Planning heuristics for SkipScan
mainThe optimizer identifies candidates for SkipScan by looking for specific plan patterns, typically involving a
Uniquenode sitting atop anIndex Scanor aMerge Appendof multipleIndex Scans.Compatible patterns include:
Unique->Index ScanUnique->Merge Append->Index Scan(multiple)
When these patterns are found, the optimizer knows the index is sorted with the distinct keys first. It then transforms the plan to use a
Custom Scan (SkipScan)which injects qualifiers into theIndex Scanto skip repeated values. TheUniquenode is preserved in the plan to ensure the targetlist projection remains compatible with PostgreSQL's expectations.Understand the role of the TimescaleDB Loader
mainThe Loader is a core component of TimescaleDB with two primary responsibilities:
Versioned Library Loading: It ensures the correct versioned shared library is loaded for each database. Since a single Postgres instance can host multiple databases with different TimescaleDB versions, the loader maps each database to its specific library (e.g., a database with version 0.8.0 will load
timescaledb-0.8.0.so).Launcher and Scheduler Management: It starts a background process called the launcher at server startup. The launcher manages individual schedulers (one per database). These schedulers check for the TimescaleDB extension and, if found, manage the scheduling of background jobs for that specific database. The launcher also manages a counter to ensure background worker usage does not exceed the configured
worker_processeslimit.
Principles for writing update and downgrade SQL scripts
mainWhen writing or modifying SQL scripts for extension updates or downgrades in TimescaleDB, follow these constraints to ensure compatibility with the extension's internal C structures and security model:
- Fully Qualify Object References: The
search_pathis locked topg_catalog, pg_tempviaheader.sql. You must use fully qualified names for all objects (except those inpg_catalog). Use the@extschema@placeholder to refer to the target installation schema (which defaults topublic). - Explicit
search_pathfor Functions: Always set an explicitsearch_pathfor functions to prevent issues. Note that setting an explicitsearch_pathprevents SQL function inlining and transaction control for procedures; in these cases, you must use fully qualified object references and operators within the function body. - Use
CREATE OR REPLACEfor Updates: While installation scripts useCREATEto prevent users from pre-creating objects, update scripts should useCREATE OR REPLACEto allow for modifications to existing definitions. - Rebuild Catalog Tables for Column Changes: If you add or remove columns from catalog tables, the tables must be completely rebuilt. The C code relies on a specific physical layout, and dropped columns will break the mapping to C structs.
- Fully Qualify Object References: The
SkipScan execution plan structure
mainWhen SkipScan is active, the execution plan follows a pattern where a
Custom Scan (SkipScan)wraps an underlyingIndex Scan. The SkipScan node iteratively restarts theIndex Scanby updating the index condition to skip over previously seen values.An example of the planned tree structure is:
Custom Scan (SkipScan) on table -> Index Scan using table_key_idx on table Index Cond: (key > NULL)After each iteration, the
key > NULLcondition is replaced withkey > [next value returned], allowing the engine to skip repeated values in the index.How submodule loading and activation works
mainTimescaleDB links module loading and activation to the license Grand Unified Configuration (GUC). The system uses a single license GUC to determine which capabilities to enable. For example, an
apachelicense key will not load Timescale-specific modules, whereas atimescalekey will.Activation is managed via
checkandassignhooks on the license GUC:check: Validates the license type.assign: Sets the capabilities-struct in the module if required.
This mechanism ensures that users cannot accidentally activate features for which they do not have a valid license.