Creating continuous aggregates
Now that you've been introduced to continuous aggregates, create your own continuous aggregate from your data.
Create an aggregate query to use in your continuous aggregate
The data we are using for this tutorial is second-by-second (tick) data for stock trades. A popular aggregate pattern used for analyzing stock data is called a candlestick. Generally, candlestick charts use 4 different aggregations over a specific interval of time (for example, 1-minute, 5-minute, or 1-day aggregates):
high
: highest stock price per intervalopen
: opening stock price per intervalclose
: closing stock price per intervallow
: lowest stock price per interval
For this example query, the time_bucket()
interval is 1 day. The
high
and low
values can be found by using the PostgreSQL MAX()
and MIN()
functions. Finally, the open
and close
values can be found by using the first()
and last()
functions.
Creating an aggregate query
- SELECT the daily candlestick values for each stock the entire 1-month dataset. This
may take a few seconds to process all of the raw data into 1-day buckets.Results:
SELECT time_bucket('1 day', "time") AS day, symbol, max(price) AS high, first(price, time) AS open, last(price, time) AS close, min(price) AS low FROM stocks_real_time srt GROUP BY day, symbol ORDER BY day DESC, symbol;
day |symbol|high |open |close |low | -----------------------------+------+--------+--------+--------+--------+ 2022-05-03 20:00:00.000 -0400|AAPL |164.9799| 159.32| 164.545| 159.25| 2022-05-03 20:00:00.000 -0400|ABBV | 151.7| 150.99| 151.32| 147.59| 2022-05-03 20:00:00.000 -0400|ABNB |158.7158| 148.84| 153.58| 145.88| 2022-05-03 20:00:00.000 -0400|ABT | 115.2| 111.64| 115.08| 111.14| 2022-05-03 20:00:00.000 -0400|ADBE | 421.93| 407.61| 419.53| 395.06| 2022-05-03 20:00:00.000 -0400|AMAT | 118.47| 114.279| 117.95| 112.04|
Create continuous aggregate from aggregate query
Now that you have the aggregation query, you can use it to create a continuous aggregate.
The CREATE MATERIALIZED VIEW
command triggers the database to create a materialized view with
the given name, in this case stock_candlestick_daily
. In the next line,
WITH (timescaledb.continuous)
instructs TimescaleDB to create a continuous
aggregate and not just a generic materialized view. Finally, the query from above
is added after the AS
keyword.
Creating a continuous aggregate from an aggregate query
- Using the aggregate query from above, create a continuous aggregate for daily
candlestick data.
CREATE MATERIALIZED VIEW stock_candlestick_daily WITH (timescaledb.continuous) AS SELECT time_bucket('1 day', "time") AS day, symbol, max(price) AS high, first(price, time) AS open, last(price, time) AS close, min(price) AS low FROM stocks_real_time srt GROUP BY day, symbol;
Notice that the SELECT
statement is the same query you wrote earlier without the
ORDER BY
clause. By default, this code both creates the aggregate
and materializes the aggregated data. That means the view is created and populated
with the aggregate calculations from your existing hypertable data.
The query may take some time to run because it needs to perform these calculations across all of your stock trade data the first time. After the calculation results are stored, querying the data from the continuous aggregate is much faster.
Run the following query to get all the data in your continuous aggregate, and note
how much faster this is than running the aggregate SELECT
query on the raw hypertable data.
SELECT * FROM stock_candlestick_daily
ORDER BY day DESC, symbol;
Real-time continuous aggregates
By default, all continuous aggregates are created as real-time aggregates. This
means that TimescaleDB always appends (or UNION
) recent data that has not yet been materialized
through a refresh policy to the output of the continuous aggregate. In the diagram
above that corresponds to the last three points of raw data, which belong to an
incomplete bucket.
note
To inspect details about a continuous aggregate, such as its configuration or the query used to define it, use the following informational view:
SELECT * FROM timescaledb_information.continuous_aggregates;
Results:
hypertable_schema|hypertable_name |view_schema|view_name |view_owner|materialized_only|compression_enabled|materialization_hypertable_schema|materialization_hypertable_name|view_definition |
-----------------+----------------+-----------+--------------+----------+-----------------+-------------------+---------------------------------+-------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
public |stocks_real_time|public |candle_one_min|tsdbadmin |false |false |_timescaledb_internal |_materialized_hypertable_3 | SELECT time_bucket('00:01:00'::interval, stocks_real_time."time") AS bucket,¶ stocks_real_time.symbol,¶ first(stocks_real_time.price, stocks_real_time."time") AS open,¶ max(stocks_real_time.price) AS high,¶ min(stocks_real_time.price) AS low,|
Next Steps
Now that your continuous aggregate is created, the next step is to create a continuous aggregate refresh policy.
Without an automatic refresh policy, your continuous aggregate won't materialize new data as it is
inserted into the stocks_real_time
hypertable. As mentioned before, when you query your continuous
aggregate, TimescaleDB performs real-time aggregation to include any unmaterialized
data. As the amount of unmaterialized data grows, this can slow down your queries.
With a continuous aggregate policy, your new data automatically materializes into your continuous aggregate, keeping the need for real-time computations low and your continuous aggregate queries efficient.
Learn more about continuous aggregates
See how real TimescaleDB users leverage continuous aggregates in the blog posts How FlightAware fuels flight prediction models for global travelers with TimescaleDB and Grafana and How I power a (successful) crypto trading bot with TimescaleDB.
Detailed information on continuous aggregates and real-time aggregation can be found in the continuous aggregates docs.
Found an issue on this page?
Report an issue!Keywords