何百万ものデータで満たされた単純なデータベース (PostgreSQL 11) があります。一日平均を出したいvalue
。そのためにtime_bucket()
関数を使用しています。
データベース スキーマ
-- create database tables + indexes
CREATE TABLE IF NOT EXISTS machine (
id SMALLSERIAL PRIMARY KEY,
name TEXT UNIQUE
);
CREATE TABLE IF NOT EXISTS reject_rate (
time TIMESTAMPTZ UNIQUE NOT NULL,
machine_id SMALLINT REFERENCES machine(id) ON DELETE CASCADE,
value FLOAT NOT NULL,
PRIMARY KEY(time, machine_id)
);
CREATE INDEX ON reject_rate (machine_id, value, time DESC);
-- hypertable
SELECT create_hypertable('reject_rate', 'time');
-- generate data with 54M rows
-- value column is generated randomly
-- this tooks minutes to finish but that's OK
INSERT INTO machine (name) VALUES ('machine1'), ('machine2');
INSERT INTO reject_rate (time, machine_id, value)
SELECT to_timestamp(generate_series(1, 54e6)), 1, random();
私がしようとしているクエリは次のとおりです。
クエリ
SELECT
time_bucket('1 day', reject_rate.time) AS day,
AVG(value)
FROM reject_rate
GROUP BY day
結果 + 説明
インデックスを使用しても、クエリの実行時間が非常に遅くなります。クエリは 626 行を返し、完了するまでに 26.5 秒かかります。90 個の TimescaleDB チャンクが作成されました。このクエリの EXPLAIN ステートメントは次のとおりです。
"GroupAggregate (cost=41.17..5095005.10 rows=54000000 width=16)"
" Group Key: (time_bucket('1 day'::interval, _hyper_120_45_chunk."time"))"
" -> Result (cost=41.17..4015005.10 rows=54000000 width=16)"
" -> Merge Append (cost=41.17..3340005.10 rows=54000000 width=16)"
" Sort Key: (time_bucket('1 day'::interval, _hyper_120_45_chunk."time"))"
" -> Index Scan using "45_86_reject_rate_time_key" on _hyper_120_45_chunk (cost=0.42..14752.62 rows=604800 width=16)"
" -> Index Scan using "50_96_reject_rate_time_key" on _hyper_120_50_chunk (cost=0.42..14752.62 rows=604800 width=16)"
" -> Index Scan using "55_106_reject_rate_time_key" on _hyper_120_55_chunk (cost=0.42..14752.62 rows=604800 width=16)"
" -> Index Scan using "60_116_reject_rate_time_key" on _hyper_120_60_chunk (cost=0.42..14752.62 rows=604800 width=16)"
" -> Index Scan using "65_126_reject_rate_time_key" on _hyper_120_65_chunk (cost=0.42..14752.62 rows=604800 width=16)"
" -> Index Scan using "70_136_reject_rate_time_key" on _hyper_120_70_chunk (cost=0.42..14752.62 rows=604800 width=16)"
" -> Index Scan using "75_146_reject_rate_time_key" on _hyper_120_75_chunk (cost=0.42..14752.62 rows=604800 width=16)"
+ ~80 another rows of Index scan
質問
インデックスを正しく作成しましたか? データベースを正しく作成しましたか? それとも、この量の行に対して TimescaleDB がそのように遅いのでしょうか?
time_bucket()
これがおそらく遅い理由です: https://github.com/timescale/timescaledb/issues/1229。提案された解決策は、連続集計ビューを使用することです。これはPostgreSQLで時系列を使用する方法として推奨されていますか?