SQL партицирование: основы и применение

Партицирование 

Партицирование — это метод разбиения большой таблицы на более мелкие, управляемые части, называемые партициями. В запросах партиция используется при фильтрации.

Как работает партицирование внутри PostgreSQL?

  • Данные распределяются по партициям на основе значений в одном или нескольких столбцах (например, по дате).
  • Каждая партиция ведет себя как отдельная таблица, но все они объединены в одну логическую таблицу.
  • Когда выполняется запрос, PostgreSQL определяет, какие партиции нужно сканировать, что уменьшает объем данных для обработки.

Из картинки вы можете увидеть, что у нас таблица sales_data поделилась по кварталам. И теперь во время запроса сканируется не вся таблица, а только какая-то определенная таблица исходя из фильтров запроса. 

Создание партицированной таблицы

-- Создание партицированной таблицы по диапазону дат
CREATE TABLE sales_data (
    order_id SERIAL,
    customer_id INT,
    amount DECIMAL(10, 2),
    order_date DATE,
    order_quartal DATE
    PRIMARY KEY (order_id)
) PARTITION BY RANGE (order_quartal);

Выбор ключа партиции

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

  • Дата: Самый часто используемый сценарий. Используется для временных данных, таких как заказы или логи, чтобы легко управлять данными по времени.
  • Категория или тип: Для данных, которые можно логически разделить на группы, например, по типу продукта.

Типы партицирования

  • Range Partitioning: Разделение по диапазонам значений (например, по диапазонам дат).
  • List Partitioning: Разделение по списку значений (например, по странам или категориям).
  • Hash Partitioning: Разделение по хеш-значению ключа (для равномерного распределения данных).

Использование партиции в запросах

  • Если таблица партицирована, то указывайте в условии WHERE/JOIN ключ партицирования
  • Нельзя преобразовывать(функции, приведения типов) ключ партицирования, это может помешать оптимизатору правильно определить, какие партиции нужно сканировать, что сильно повлияет на скорость запроса.
SELECT 
    date_trunc('quarter', order_quartal) AS quarter,
    SUM(amount) AS total_sales
FROM 
    sales_data
WHERE
    quarter in ('2023-04-01', 2023-07-01') -- в условии используем ключ партицирования
GROUP BY 
    quarter

Партицирование - это must have для ускорения запросов, пользоваться им нужно всегда, если ваша таблица больше 100 тыс строк ;)