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

Что такое портиция?

2.0 Middle🔥 131 комментариев
#SQL и базы данных

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

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

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

Партицирование: Разделение Больших Таблиц на Части

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

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

Вместо одной огромной таблицы с миллионами строк, ты разбиваешь её на несколько меньших таблиц, каждая содержит часть данных. При запросе база данных обращается только к релевантным партициям.

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

1. Range Partitioning (Диапазонное)

Разделение по диапазону значений, часто по датам:

CREATE TABLE events (
    id BIGINT,
    user_id UUID,
    event_timestamp TIMESTAMP,
    data JSONB
) PARTITION BY RANGE (event_timestamp);

-- Партиция для января 2026
CREATE TABLE events_2026_01 PARTITION OF events
    FOR VALUES FROM ('2026-01-01') TO ('2026-02-01');

-- Партиция для февраля 2026
CREATE TABLE events_2026_02 PARTITION OF events
    FOR VALUES FROM ('2026-02-01') TO ('2026-03-01');

-- Партиция для марта 2026
CREATE TABLE events_2026_03 PARTITION OF events
    FOR VALUES FROM ('2026-03-01') TO ('2026-04-01');

Преимущество: Легко управлять старыми партициями (удалять, архивировать), быстрый поиск по датам.

2. List Partitioning (По Спискам)

Разделение по конкретным значениям:

CREATE TABLE user_accounts (
    id UUID,
    country VARCHAR,
    user_type VARCHAR,
    balance DECIMAL
) PARTITION BY LIST (country);

CREATE TABLE accounts_us PARTITION OF user_accounts
    FOR VALUES IN ('US', 'CA');

CREATE TABLE accounts_eu PARTITION OF user_accounts
    FOR VALUES IN ('UK', 'DE', 'FR', 'IT');

CREATE TABLE accounts_asia PARTITION OF user_accounts
    FOR VALUES IN ('JP', 'CN', 'IN');

Преимущество: Естественное разделение данных по категориям.

3. Hash Partitioning (По Хешу)

Разделение на основе хеша значения:

CREATE TABLE transactions (
    id BIGINT,
    user_id UUID,
    amount DECIMAL,
    created_at TIMESTAMP
) PARTITION BY HASH (user_id);

CREATE TABLE transactions_p0 PARTITION OF transactions
    FOR VALUES WITH (MODULUS 4, REMAINDER 0);

CREATE TABLE transactions_p1 PARTITION OF transactions
    FOR VALUES WITH (MODULUS 4, REMAINDER 1);

CREATE TABLE transactions_p2 PARTITION OF transactions
    FOR VALUES WITH (MODULUS 4, REMAINDER 2);

CREATE TABLE transactions_p3 PARTITION OF transactions
    FOR VALUES WITH (MODULUS 4, REMAINDER 3);

Преимущество: Равномерное распределение данных, уменьшает горячие точки.

Преимущества Партицирования

Улучшение производительности: Запросы, ограниченные партицией, обрабатываются быстрее ✅ Управление большими данными: Проще работать с таблицами размером TB+ ✅ Параллельная обработка: Разные партиции можно обрабатывать параллельно ✅ Удаление старых данных: Можно просто удалить старую партицию вместо DELETE запроса ✅ Index эффективность: Меньше данных — меньше индекс

Недостатки

Сложность: Требует планирования и управления ❌ Maintenence: Нужно создавать новые партиции (например, ежемесячно) ❌ Ограничения: Невозможно использовать все типы индексов на всех колонках ❌ JOIN сложность: JOIN между партициями может быть медленнее

Практический Пример для Data Engineer

-- Таблица логов с временным партицированием
CREATE TABLE logs (
    id BIGSERIAL,
    log_level VARCHAR,
    message TEXT,
    created_at TIMESTAMP NOT NULL
) PARTITION BY RANGE (created_at);

-- Создание партиций на лету
DO $$
DECLARE
    start_date DATE := '2026-01-01';
    end_date DATE;
    partition_name TEXT;
BEGIN
    FOR i IN 0..11 LOOP
        end_date := start_date + INTERVAL '1 month';
        partition_name := 'logs_' || TO_CHAR(start_date, 'YYYY_MM');
        
        EXECUTE format(
            'CREATE TABLE %I PARTITION OF logs FOR VALUES FROM (%L) TO (%L)',
            partition_name, start_date, end_date
        );
        
        start_date := end_date;
    END LOOP;
END $$;

-- Запрос к конкретной партиции
SELECT * FROM logs WHERE created_at >= '2026-03-01' AND created_at < '2026-04-01';
-- PostgreSQL автоматически обратится только к partition logs_2026_03

Partition Pruning (Оптимизация)

Это когда оптимизатор автоматически исключает ненужные партиции:

-- Этот запрос обратится ТОЛЬКО к партициям за 2026-03
SELECT COUNT(*) FROM events WHERE event_timestamp >= '2026-03-01';
-- Партиции за 2026-01 и 2026-02 будут полностью пропущены

-- Этот запрос требует сканирования всех партиций
SELECT COUNT(*) FROM events WHERE user_id = 'some-uuid';
-- Нет partition pruning, так как условие не на partition key

Auto-partitioning в Python

import pandas as pd
from datetime import datetime, timedelta

def load_data_with_partitioning(df, table_name, partition_column, partition_type='monthly'):
    """
    Загружает данные в БД с автоматическим партицированием по датам
    """
    if partition_type == 'monthly':
        df[partition_column] = pd.to_datetime(df[partition_column])
        df['partition'] = df[partition_column].dt.to_period('M')
        
        for partition, group in df.groupby('partition'):
            partition_name = f"{table_name}_{partition}".replace('-', '_')
            group.to_sql(
                partition_name,
                con=db_engine,
                if_exists='append',
                index=False
            )
            print(f"Загружена партиция: {partition_name}")

# Использование
df = pd.read_csv('large_events.csv')
load_data_with_partitioning(df, 'events', 'created_at', 'monthly')

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

  1. Таблица > 1 GB: При большом размере партицирование даёт значительный выигрыш
  2. Временные данные: Особенно для логов, событий, временных рядов
  3. Archival requirements: Когда нужно удалять старые данные целыми блоками
  4. High write volume: Улучшает параллелизм записи
  5. Range queries: Когда часто запрашиваешь диапазоны данных

Когда НЕ Использовать

❌ Таблица < 100 MB ❌ Частые FULL TABLE JOINS ❌ Условия запросов никогда не используют partition key ❌ Простые OLTP приложения

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

Что такое портиция? | PrepBro