← Назад к вопросам

Что такое разделение таблиц на части?

1.6 Junior🔥 141 комментариев
#Soft Skills и карьера

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разделение таблиц на части (Table Partitioning)

Разделение таблиц на части (Partitioning) — это техника оптимизации БД, при которой большая таблица физически разбивается на несколько более мелких таблиц (разделов или партиций), но логически они остаются единой сущностью. Каждый раздел содержит подмножество строк в соответствии с критериями разбиения.

Основная идея

Вместо хранения всех 100 миллионов строк в одной огромной таблице, мы разбиваем их, например, по дате:

  • Раздел 2024 Q1: строки с января по март
  • Раздел 2024 Q2: строки с апреля по июнь
  • Раздел 2024 Q3: строки с июля по сентябрь
  • И т.д.

Для приложения это выглядит как одна таблица, но СУБД работает с отдельными разделами, значительно ускоряя операции.

Стратегии разбиения

1. Range Partitioning (разбиение по диапазону)

Данные разбиваются по диапазону значений (например, по датам или ID):

CREATE TABLE orders (
    id BIGINT,
    order_date DATE,
    amount DECIMAL(10, 2),
    customer_id BIGINT
) PARTITION BY RANGE (YEAR(order_date)) (
    PARTITION p2022 VALUES LESS THAN (2023),
    PARTITION p2023 VALUES LESS THAN (2024),
    PARTITION p2024 VALUES LESS THAN (2025),
    PARTITION pmax VALUES LESS THAN MAXVALUE
);

2. List Partitioning (разбиение по списку)

Данные разбиваются по конкретным значениям:

CREATE TABLE employees (
    id INT,
    name VARCHAR(50),
    department VARCHAR(50)
) PARTITION BY LIST (department) (
    PARTITION p_sales VALUES IN ("Sales", "Support"),
    PARTITION p_engineering VALUES IN ("Engineering", "QA"),
    PARTITION p_admin VALUES IN ("HR", "Finance")
);

3. Hash Partitioning (разбиение по хешу)

Данные распределяются по разделам на основе хеш-функции:

CREATE TABLE user_logs (
    id BIGINT,
    user_id BIGINT,
    action VARCHAR(50),
    timestamp DATETIME
) PARTITION BY HASH (user_id) PARTITIONS 10;

Здесь данные распределяются равномерно по 10 разделам. Каждая запись идёт в раздел hash(user_id) mod 10.

4. Composite/Key Partitioning (комбинированное разбиение)

Комбинирует несколько способов:

CREATE TABLE sales (
    id INT,
    region VARCHAR(50),
    sales_date DATE,
    amount DECIMAL(10, 2)
) PARTITION BY RANGE (YEAR(sales_date))
  SUBPARTITION BY LIST (region) (
    PARTITION p2024 VALUES LESS THAN (2025) (
        SUBPARTITION sp_na VALUES IN ("USA", "Canada"),
        SUBPARTITION sp_eu VALUES IN ("UK", "Germany", "France"),
        SUBPARTITION sp_asia VALUES IN ("Japan", "India")
    )
);

Преимущества

1. Производительность запросов

Если в WHERE используется критерий разбиения, СУБД может пропустить ненужные разделы:

-- Запрос автоматически пропустит разделы за 2022 и 2023 год
SELECT * FROM orders 
WHERE order_date >= 2024-01-01 AND order_date < 2025-01-01;

2. Управление данными

Легче удалять старые данные, удаляя целые разделы:

-- Удалить данные за 2022 год за миллисекунды
ALTER TABLE orders DROP PARTITION p2022;

3. Параллельная обработка

запрос может обрабатывать несколько разделов параллельно.

4. Размер индексов

Индексы разделяются, они становятся меньше и быстрее.

Недостатки

1. Сложность

  • Выбор правильной стратегии разбиения требует глубокого понимания данных
  • Сложнее писать и отладить запросы

2. Maintenance

Нужно регулярно добавлять новые разделы:

ALTER TABLE orders ADD PARTITION (PARTITION p2025 VALUES LESS THAN (2026));

3. Ограничения

  • Первичный ключ должен включать все колонки партиционирования (в некоторых СУБД)
  • Некоторые типы индексов не работают с разделёнными таблицами

4. Не всегда помогает

Если критерий разбиения не совпадает с критериями ваших запросов, výhod может быть мало.

Практический пример в Java

public class OrderService {
    private JdbcTemplate jdbcTemplate;
    
    // Приложение не нужно знать о разбиении
    public List<Order> getOrders(LocalDate startDate, LocalDate endDate) {
        return jdbcTemplate.query(
            "SELECT * FROM orders WHERE order_date BETWEEN ? AND ?",
            ps -> {
                ps.setDate(1, Date.valueOf(startDate));
                ps.setDate(2, Date.valueOf(endDate));
            },
            new OrderRowMapper()
        );
    }
    
    // СУБД автоматически использует нужные разделы
}

Когда использовать партиционирование

Используйте, когда:

  • Таблица > 1 ГБ
  • Часто удаляются целые наборы данных
  • Запросы часто используют одну колонку в WHERE
  • Нужна горизонтальная масштабируемость

Не используйте, когда:

  • Таблица маленькая (< 100 МБ)
  • Запросы редко используют критерий разбиения
  • Вам не нужно удалять большие наборы данных

Шардирование vs Партиционирование

  • Партиционирование: разбиение на одном сервере (vertical partitioning в одной БД)
  • Шардирование: разбиение данных между несколькими серверами (horizontal distribution)

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