Что произойдёт, если таблица разбита на партиции по одному столбцу, а запрос выполняется по условию на другом столбце?

«Что произойдёт, если таблица разбита на партиции по одному столбцу, а запрос выполняется по условию на другом столбце?» — вопрос из категории Базы данных, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Это приведёт к полному сканированию таблицы (Full Table Scan), так как механизм партиционирования не сможет выполнить "отсечение партиций" (partition pruning). Запрос будет вынужден проверить каждую партицию, что сведёт на нет основное преимущество партиционирования — уменьшение объёма данных для чтения.

Конкретный пример в PostgreSQL:

-- Создаём таблицу, партиционированную по дате
CREATE TABLE sensor_data (
    sensor_id INT,
    recorded_at DATE,
    value DECIMAL
) PARTITION BY RANGE (recorded_at);

CREATE TABLE sensor_data_2023 PARTITION OF sensor_data
    FOR VALUES FROM ('2023-01-01') TO ('2024-01-01');
CREATE TABLE sensor_data_2024 PARTITION OF sensor_data
    FOR VALUES FROM ('2024-01-01') TO ('2025-01-01');

-- Запрос по партиционному ключу — БЫСТРО (чтение только из одной партиции)
SELECT * FROM sensor_data WHERE recorded_at = '2024-06-15'; -- Сканируется только sensor_data_2024

-- Запрос по НЕпартиционному ключу — МЕДЛЕННО (чтение из ВСЕХ партиций)
SELECT * FROM sensor_data WHERE sensor_id = 123; -- Сканируется sensor_data_2023 И sensor_data_2024

Как оптимизировать такой сценарий:

  1. Добавить индекс на столбец sensor_id. Это ускорит поиск внутри каждой партиции, но не избавит от необходимости обхода всех партиций.
  2. Изменить стратегию партиционирования, если это возможно по логике данных. Например, сделать составной ключ PARTITION BY RANGE (recorded_at, sensor_id) или хэш-партиционирование по sensor_id.
  3. Спроектировать запросы так, чтобы они всегда включали условие по партиционному ключу. Например, сначала найти диапазоны дат для нужного sensor_id, а затем делать запрос с фильтром и по recorded_at.

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