Медленный запрос TimescaleDB с использованием time_bucket - PullRequest
0 голосов
/ 19 июня 2019

У меня есть простая база данных (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

Result + EXPLAIN

Время выполнения запроса очень медленное, даже если я использую индексы. Запрос возвращает 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?

1 Ответ

0 голосов
/ 19 июня 2019

Мне интересно, сколько времени это займет со встроенными функциями Postgres:

SELECT date_trunc('day', rr.time) as day,
       AVG(value)
FROM reject_rate rr
GROUP BY date_trunc('day', rr.time);
...