Learning Platform
Глоссарий Troubleshooting
Урок 06.02 · 18 мин
Начальный
keysnatural-keysurrogate-keykey-design

Natural keys vs surrogate keys: компромиссы

В прошлом уроке мы построили иерархию ключей и сказали: из нескольких candidate keys проектировщик выбирает один primary key. Теперь — главный вопрос этого выбора. Брать в качестве ключа что-то из реальных данных (email, ИНН, номер паспорта) или сгенерировать искусственный идентификатор, не имеющий смысла? Это разделение на natural keys и surrogate keys, и оно — одно из самых частых решений в проектировании.

Сразу честная рамка: это компромисс, а не «правильный ответ». У каждого подхода есть реальная сила. Но в современном проектировании, особенно в аналитике и data engineering, surrogate keys стали стандартом — и важно понимать не догму, а причины.

Natural key: ключ из реальных данных

Natural key (он же business key) — это ключ, составленный из атрибутов, которые имеют смысл в предметной области и существовали бы, даже если бы базы данных не было.

Примеры natural keys:

  • email пользователя.
  • ИНН организации, номер паспорта человека.
  • VIN автомобиля (17-символьный код).
  • ISBN книги.
  • Номер счёта-фактуры (invoice number).
  • Код аэропорта IATA (SVO, JFK).

Объединяет их то, что это реальные идентификаторы из мира, а не выдумка базы. Бизнес уже использует их в документах, разговорах, других системах.

Сильные стороны natural key:

  • Осмысленность. Глядя на SVO, человек понимает «Шереметьево». Глядя на user_id = 84217, не понимает ничего.
  • Естественная защита от дубликатов. Если ключ — это ИНН, то два tuple с одним ИНН физически невозможны — natural key сам по себе несёт уникальность сущности.
  • Не нужен лишний JOIN при сверке. Если в двух системах объект опознаётся по одному business key, их данные можно сопоставить напрямую.

Слабые стороны natural key

Теперь — почему natural key проблематичен как primary key. Эти проблемы и привели к доминированию surrogate keys.

1. Natural key меняется. Это главная проблема. Email пользователь меняет. Организация меняет название. Страны переименовывают города. ИНН компании может смениться при реорганизации. А primary key обязан быть стабильным (помните критерий из прошлого урока): если он меняется, изменение нужно протащить через все foreign keys всех таблиц, которые на него ссылаются. Один UPDATE ключа может превратиться в каскад обновлений по десяткам таблиц и миллионам строк.

2. Natural key широкий. VIN — 17 символов. Email — до 254. ISBN — 13 цифр. Составной natural key («код страны + код региона + номер») — ещё больше. Чем шире ключ, тем толще индекс, тем меньше записей помещается на страницу, тем медленнее JOIN. Целочисленный surrogate key — 4-8 байт; этому уроку и физике посвящён последний урок модуля.

3. Natural key не всегда известен сразу. Клиент регистрируется — паспорта ещё нет. Заказ создаётся — номер счёта-фактуры появится позже. А primary key обязан быть NOT NULL с момента вставки строки. Если ключа ещё нет, строку нельзя создать — абсурдная ситуация.

4. Natural key может оказаться не таким уникальным. Реальный мир грязнее, чем кажется. Бывают повторно выданные ИНН, опечатки в документах, исторические VIN с нарушением формата. Ключ, который «по правилам уникален», на практике иногда не уникален — и СУБД на этом сломается.

5. Natural key утекает в чужие системы. Если primary key — это email или номер паспорта, то этот ключ расползается по логам, URL, foreign keys других сервисов. Это и приватность (PII в ключах), и связанность: смена ключа ломает всех.

Почему изменяемый natural key опасен как primary key
Primary key = emailВ качестве primary key выбран natural key — email пользователя.
пользователь сменил email
UPDATE users SET email = ...Поменять значение ключа в одной строке — кажется простым.
но на email ссылаются FK
Каскад правок в orders, payments, logs, ...Каждая таблица с foreign key на email должна быть обновлена синхронно. Дорого и рискованно.

Surrogate key: искусственный идентификатор

Surrogate key — это искусственный идентификатор, лишённый собственного смысла, сгенерированный системой исключительно для того, чтобы идентифицировать строку.

Типичные формы: автоинкрементное целое (user_id = 1, 2, 3, ...), UUID, hash от business key, Snowflake ID. Стратегии генерации детально разбираются в уроке 4 этого модуля; сейчас важно само понятие.

Ключевое свойство surrogate key — у него нет связи с реальным миром. user_id = 84217 не значит ничего. И именно отсутствие смысла — его сила.

Сильные стороны surrogate key:

  • Стабильность. У surrogate key нет причин меняться: он ни на что в реальном мире не завязан. Email пользователь сменит — user_id останется. Это полностью снимает первую и главную проблему natural key.
  • Узость и единообразие. Целочисленный surrogate key — 4 или 8 байт, всегда один столбец. Узкий ключ -> компактный индекс -> быстрый JOIN.
  • Доступен сразу. Систему просят сгенерировать ключ в момент вставки строки — он есть всегда, NOT NULL соблюдается тривиально.
  • Гарантированная уникальность. Уникальность обеспечивает генератор, а не «надежда, что в реальных данных не будет дубля».
  • Не утекает смысл. Surrogate key можно безопасно показывать в URL и логах — он ничего не раскрывает (UUID — особенно, его нельзя перебрать).

Слабые стороны surrogate key:

  • Бессмысленность. user_id = 84217 ни о чём не говорит человеку. Для отладки и сверки всё равно нужны осмысленные атрибуты.
  • Не защищает от дублирования сущности. Surrogate key уникален всегда — но он не мешает завести двух разных пользователей с одним email. Surrogate key гарантирует уникальность СТРОКИ, но не уникальность СУЩНОСТИ.

Последний пункт критичен и часто упускается.

WARNING

Surrogate key как primary key НЕ отменяет natural key. Если в системе есть business key (email, ИНН), на него почти всегда нужно отдельно поставить UNIQUE-ограничение. Иначе: surrogate key честно даст каждой строке уникальный id, но ничто не помешает создать две строки-дубликата с одинаковым email. Правильный паттерн — surrogate key как PRIMARY KEY плюс natural key как UNIQUE. Surrogate отвечает за идентификацию строки, UNIQUE на natural key — за уникальность сущности.

CREATE TABLE users (
    user_id INTEGER PRIMARY KEY,        -- surrogate key: идентифицирует строку
    email   TEXT NOT NULL UNIQUE,       -- natural key: гарантирует уникальность сущности
    name    TEXT NOT NULL
);
-- user_id даёт стабильную узкую идентификацию,
-- UNIQUE(email) не даёт завести двух пользователей с одним email.
-- Нужны ОБА.

Сравнение

КритерийNatural keySurrogate key
Источникреальные данные предметной областисгенерирован системой
Смысл для человекаестьнет
Стабильностьможет менятьсястабилен
Шириначасто широкий (строки, составные)узкий (4-8 байт integer)
Доступность при вставкене всегда есть сразуесть всегда
Защита от дубля сущностиесть (встроена в ключ)нет (нужен отдельный UNIQUE)
Утечка смысла в URL/логида (риск PII)нет
Стандартный паттерн: surrogate как PK + natural как UNIQUE
surrogate keyuser_id INTEGER PRIMARY KEY. Стабильная узкая идентификация строки, стабильная цель для foreign keys.
дополняется
natural / business keyemail TEXT UNIQUE. Гарантирует, что не появятся две строки-дубликата одной сущности.

Почему surrogate key стал стандартом — и где natural уместен

В современном проектировании, особенно в OLTP и в аналитических warehouse, surrogate key — выбор по умолчанию для primary key. Причина — совокупность: стабильность (не ломает foreign keys), узость (быстрый JOIN), доступность сразу. В размерном моделировании это вообще обязательно: surrogate key — единственный способ корректно реализовать Slowly Changing Dimensions (отдельный модуль курса), где у одной сущности во времени несколько версий-строк.

Но natural key не исчезает и остаётся уместен:

  • Как UNIQUE-ограничение рядом с surrogate primary key — почти всегда.
  • Когда natural key гарантированно стабилен и узок — например, ISO-код страны (RU, US) — двухсимвольный, неизменный; для маленькой справочной таблички он может быть и primary key.
  • В Data Vault hub-таблицы хранят именно business keys — но и там surrogate hash key используется как технический ключ (модуль про Data Vault).

Главный вывод: понимайте компромисс. Surrogate key решает проблемы изменяемости и ширины — поэтому он стандарт. Natural key несёт смысл и уникальность сущности — поэтому он почти всегда нужен как UNIQUE рядом. Грамотная модель обычно использует оба.

Суррогатные ключи в dbt — generate_surrogate_key

Попробуй сам

Спроектируйте таблицу companies для системы учёта контрагентов. Известно: у компании есть ИНН (в теории уникален, но в реальных данных встречаются дубли и опечатки), название (меняется при ребрендинге), дата регистрации.

  1. Попробуйте сделать primary key = ИНН (natural key). Перечислите минимум три проблемы, с которыми вы столкнётесь: что произойдёт при опечатке в ИНН, при смене ИНН, при ссылках из других таблиц.
  2. Перепроектируйте: добавьте surrogate key company_id как PRIMARY KEY. Куда теперь деть ИНН? Объясните, почему оставить ИНН вообще без ограничения — ошибка, и почему UNIQUE на ИНН — правильно (и что делать, если в данных реально есть дубли ИНН).
  3. Напишите итоговый CREATE TABLE. Создайте таблицу contracts, ссылающуюся на companies. Подумайте: на какой столбец companies должен указывать foreign key — на surrogate key или на ИНН? Почему именно на surrogate key?
  4. Сформулируйте одним предложением, за что в вашей схеме отвечает surrogate key, а за что — UNIQUE на natural key.

Проверка знанийKnowledge check
Почему использование surrogate key как primary key не отменяет необходимости natural (business) key, и что произойдёт, если оставить natural key вообще без ограничений в схеме?
ОтветAnswer
Surrogate key и natural key решают две разные задачи, поэтому surrogate key не заменяет natural key. Surrogate key — это искусственный идентификатор без смысла, и он гарантирует уникальность СТРОКИ: каждая строка получает свой собственный id. Но он ничего не знает о предметной области и поэтому НЕ гарантирует уникальность СУЩНОСТИ — он не мешает создать две разные строки-дубликата, описывающие один и тот же реальный объект. Например, при surrogate primary key user_id ничто не помешает вставить двух пользователей с одинаковым email: оба получат разные user_id, и СУБД будет считать их разными строками, хотя это один человек. Natural (business) key — email, ИНН, VIN — наоборот, несёт уникальность сущности из реального мира. Если оставить natural key вообще без ограничений в схеме, в таблицу попадут дубликаты сущностей: несколько строк на одного клиента, на одну компанию, на один товар. Это разрушает целостность данных — аналитика начнёт считать одну сущность за несколько, агрегаты завысятся, связи запутаются. Поэтому правильный паттерн — surrogate key как PRIMARY KEY (стабильная узкая идентификация строки и цель для foreign keys) плюс natural key как UNIQUE-ограничение (защита от дублирования сущности). Нужны оба: они закрывают разные аспекты целостности.

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 4. Что такое surrogate key?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5