Ответ
Кластеризованный индекс (обычно PRIMARY KEY) определяет физический порядок данных в таблице. Его не всегда стоит использовать в качестве основного ключа по следующим причинам:
- Частые вставки в неконце таблицы: При вставке записи с ключом, попадающим в середину таблицы, происходит фрагментация страниц (page splits), что дорого с точки зрения производительности и места.
- Большой размер ключа: Ключ кластеризованного индекса включается во все некластеризованные (вторичные) индексы как указатель на строку. Большой ключ увеличивает размер всех вторичных индексов.
- Неэффективный доступ по другим полям: Если основные запросы фильтруют или соединяют таблицы по другим столбцам (например,
user_id,created_at), кластеризация по первичному ключу может быть неоптимальной.
Пример проблемного сценария — UUID как первичный ключ:
-- Случайные UUID приводят к фрагментации при вставках
CREATE TABLE orders (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(), -- Кластеризованный индекс
user_id INT NOT NULL,
amount DECIMAL
);
-- Запросы по user_id будут неэффективны без отдельного индекса.
Альтернативное решение: Использовать суррогатный, последовательно возрастающий ключ для кластеризации и создать отдельный уникальный индекс для бизнес-ключа.
CREATE TABLE orders (
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, -- Узкий, возрастающий ключ
external_id UUID UNIQUE NOT NULL, -- Бизнес-идентификатор
user_id INT NOT NULL,
amount DECIMAL,
INDEX idx_user_id (user_id) -- Эффективный индекс для частых запросов
);