alexeyfv

Опубликовано

- 2 мин чтения

PostgreSQL vs TimescaleDB: сравнение производительности

PostgreSQL TimescaleDB Performance Analytics SQL
img of PostgreSQL vs TimescaleDB: сравнение производительности

TimescaleDB — популярное расширение PostgreSQL для работы с временными рядами (time-series). В нём есть функционал, позволяющий оптимизировать хранение данных и запросы к ним.

В этой статье я сравню производительность TimescaleDB и PostgreSQL с тестовым аналитическим запросом.

Установка и запуск TimescaleDB в Docker

У TimescaleDB есть готовый Docker образ. Конфигурация аналогична обычной базе Postgres.

  # docker-compose.yml
services:
  timescaledb:
    container_name: timescaledb
    image: timescale/timescaledb:latest-pg17
    restart: unless-stopped
    shm_size: 1g
    ports:
      - 5432:5432
    environment:
      POSTGRES_DB: 'timescaledb'
      POSTGRES_USER: 'sa'
      POSTGRES_PASSWORD: 'qweQWE123!!'
      PGDATA: /var/lib/postgresql/17/docker
    volumes:
      - timescaledb_data:/var/lib/postgresql

volumes:
  timescaledb_data:

Запускаем базу командой:

  docker compose -f docker-compose.yml up -d

Создание hypertable в TimescaleDB

Таблицы в TimescaleDB называются hypertables. Они создаются как обычные Postgres таблицы с небольшим дополнением.

  CREATE TABLE billing_data (
    billed_cost numeric(25,15),
    charge_date timestamptz,
    resource_id int4)
WITH (
    -- Указываем, что это hypertable
    timescaledb.hypertable = true,
    -- Разбиваем данные на части (chunks) размером в 1 день
    timescaledb.chunk_interval='1 day',
    -- Группируем данные по ресурсу
    timescaledb.segmentby='resource_id'
    -- Сортируем данные по дате
    timescaledb.orderby='charge_date'
);

Что такое hypertable?

Hypertable — это специальный тип таблицы TimescaleDB, который автоматически разбивает данные на части (chunks), оптимизирует их хранение и доступ для аналитических запросов.

Как работает сегментирование данных в hypertable?

TimescaleDB может использовать колончатое хранение данных (Hypercore), автоматически разбивает таблицу на chunks и поддерживает его в актуальном состоянии. Картинка взята из документации TimescaleDB.

Сегментирование данных в hypertable

При достаточном объёме данных и низкой кардинальности (небольшом количестве уникальных ресурсов), производительность аналитических запросов на hypertable может быть значительно выше, чем на обычной таблице Postgres. Достигается это за счёт высокой плотности данных и оптимизации доступа к ним.

Бенчмарк: сравнение TimescaleDB и PostgreSQL

В тестовом аналитическом запросе я считал ежедневные траты облачных ресурсов за последние 30 дней.

Для замеров я использовал библиотеку BenchmarkDotNet. Исходный код бенчмарка доступен в моём репозитории на GitHub.

  -- Postgres
SELECT
    date_bin('1 day', charge_date, TIMESTAMP 'epoch') AS day,
    resource_id,
    SUM(billed_cost) AS total_cost
FROM billing_data
WHERE charge_date >= now() - interval '30 days'
GROUP BY day, resource_id

-- TimescaleDB
SELECT
    time_bucket(INTERVAL '1 day', charge_date) AS day,
    resource_id,
    SUM(billed_cost) AS total_cost
FROM billing_data
WHERE charge_date >= now() - interval '30 days'
GROUP BY day, resource_id

Чем time_bucket отличается от date_bin?

Функции time_bucket и date_bin похожи. Они позволяют группировать данные по произвольным интервалам времени. Однако time_bucket оптимизирован для работы с hypertable и может обеспечить лучшую производительность в TimescaleDB.

Результаты бенчмарка

Результаты бенчмарка на графике ниже. Ось Y — медианное время выполнения, ось X — количество ресурсов в таблице.

Результаты бенчмарка

Размер таблицы был фиксированным — 1 млн строк и я изменял только кардинальность путём увеличения количества уникальных ресурсов от 10 до 1 млн. То есть значение кардинальности зависело от соотношения уникальных ресурсов к количеству данных.

Как видно из результатов, производительность TimescaleDB на 15% - 28% лучше при низкой кардинальности (до около 10 000 уникальных ресурсов, или около 100 строк данных на ресурс).

Если кардинальность выше (более 20 000 уникальных ресурсов), время выполнения запроса становится на 45% - 165% хуже.

Заключение

TimescaleDB хорошо подходит для аналитических запросов, если данные имеют низкую кардинальность и достаточный объём. В таких случаях он может обеспечить значительное улучшение производительности по сравнению с обычным Postgres.

В следующих постах я поэкспериментирую с другими данными и запросами, чтобы понять, в каких сценариях TimescaleDB может быть особенно полезен.