Суррогатный ключ¶
Суррогатный ключ (англ. surrogate key) — в проектировании баз данных это уникальный идентификатор записи (кортежа) в таблице, который не имеет семантического (смыслового) значения и не основан на данных предметной области. В отличие от естественного ключа, который образуется из одного или нескольких атрибутов, описывающих сущность (например, номер паспорта, ИНН, VIN-код автомобиля), суррогатный ключ создаётся исключительно для внутренних нужд системы и не несёт информации о самой записи.
¶История и предпосылки появления
Концепция суррогатных ключей возникла в 1970-х годах в связи с развитием реляционной модели данных, предложенной Эдгаром Коддом. В ранних реляционных СУБД для идентификации строк использовались естественные ключи — комбинации полей, уникально определяющие запись. Однако на практике естественные ключи обладали рядом недостатков:
- Изменяемость: значения естественных ключей могли меняться с течением времени (например, смена фамилии или номера паспорта). При изменении ключа приходилось обновлять все связанные записи в других таблицах (каскадное обновление), что приводило к сложностям и риску потери целостности данных.
- Составные ключи: для обеспечения уникальности часто требовалось несколько полей (например, «Номер цеха» + «Дата смены» + «Табельный номер сотрудника»). Такие ключи были громоздкими, замедляли индексацию и усложняли написание запросов.
- Зависимость от бизнес-логики: естественные ключи привязаны к правилам предметной области. Если эти правила менялись (например, вводилась новая система нумерации), требовалась перестройка всей структуры данных.
В 1979 году Кодд ввёл понятие «суррогатный ключ» как искусственный атрибут, создаваемый системой и не имеющий внешнего значения. В 1980-х годах эта концепция получила широкое распространение в коммерческих СУБД (Oracle, DB2, Sybase, Microsoft SQL Server) и стала стандартом де-факто в проектировании реляционных баз данных.
¶Виды суррогатных ключей
Суррогатные ключи можно классифицировать по способу генерации и типу данных:
¶По способу генерации
- Автоинкрементные (identity): целочисленные значения, автоматически увеличивающиеся на единицу при вставке каждой новой записи. Реализованы в большинстве современных СУБД (SERIAL в PostgreSQL, AUTO_INCREMENT в MySQL, IDENTITY в Microsoft SQL Server). Просты, но не гарантируют уникальности при переносе данных между системами (например, при репликации).
- Глобально уникальные идентификаторы (GUID/UUID): 128-битные числа, генерируемые по алгоритму, обеспечивающему уникальность без централизованного управления. Примеры: UUID версии 4 (случайный), UUID версии 1 (на основе времени и MAC-адреса). Используются в распределённых системах, где записи могут создаваться на разных узлах (например, в Microsoft SQL Server — тип
uniqueidentifier, в PostgreSQL —uuid). - Последовательности (sequences): отдельные объекты базы данных, генерирующие уникальные числа. Могут быть настроены на шаг, начальное значение и кэширование. Используются в Oracle, PostgreSQL, IBM Db2. Позволяют гибко управлять генерацией, но требуют отдельного обслуживания.
- Хеш-функции: вычисление ключа на основе хеша от одного или нескольких полей записи (например, SHA-256). Применяются в аналитических базах данных (Data Vault, ClickHouse) для обеспечения уникальности без дополнительного счётчика.
¶По типу данных
- Целочисленные: самый распространённый тип. Занимают 4 байта (INT) или 8 байт (BIGINT). Быстро индексируются и эффективны для соединений (JOIN). Пример:
id INT PRIMARY KEY AUTO_INCREMENT. - Строковые: обычно GUID/UUID в виде строки (36 символов с дефисами). Занимают больше места (16 байт в бинарном виде, 36 байт в текстовом), но обеспечивают глобальную уникальность. Пример:
id CHAR(36) PRIMARY KEY. - Бинарные: GUID в виде массива байтов (16 байт). Используются в некоторых СУБД (например,
uniqueidentifierв SQL Server может храниться как 16-байтовое значение).
¶Устройство и характеристики
Суррогатный ключ обычно объявляется первичным ключом (PRIMARY KEY) таблицы. Ключевые характеристики:
- Уникальность: значение никогда не повторяется в пределах таблицы. Обеспечивается либо автоматической генерацией, либо проверкой на уровне СУБД.
- Неизменяемость: значение не должно меняться после создания записи. Даже если запись «удаляется» логически (soft delete), ключ не переиспользуется.
- Несемантичность: ключ не несёт информации о сущности. Например, по значению 1024 нельзя определить, относится ли запись к сотруднику, товару или заказу.
- Простота: обычно это одно поле (не составной ключ), что упрощает написание запросов и создание внешних ключей (FOREIGN KEY).
Пример создания таблицы с суррогатным ключом на PostgreSQL:
``sql CREATE TABLE employees ( id SERIAL PRIMARY KEY, employee_code VARCHAR(20) UNIQUE, -- естественный ключ (может меняться) full_name VARCHAR(100), hire_date DATE ); ``
Здесь id — суррогатный ключ, а employee_code — естественный ключ, объявленный как уникальный (UNIQUE), но не первичный.
¶Применение
Суррогатные ключи используются в большинстве современных реляционных баз данных, а также в некоторых NoSQL-системах (например, в документоориентированных БД для идентификации документов). Основные области применения:
- Реляционные СУБД (SQL): в качестве первичных ключей для таблиц фактов и измерений в схемах «звезда» и «снежинка» (Data Warehouse). В OLTP-системах — для всех таблиц, где естественные ключи нестабильны или громоздки.
- Объектно-реляционное отображение (ORM): фреймворки (Hibernate, Entity Framework, Django ORM) по умолчанию генерируют суррогатные ключи для классов сущностей. Это упрощает маппинг и обеспечивает единообразие.
- Распределённые системы: GUID/UUID позволяют создавать уникальные записи на разных серверах без синхронизации счётчиков, что критично для микросервисной архитектуры и репликации.
- Аналитические системы: в Data Vault суррогатные ключи используются для хабов (hub), связей (link) и сателлитов (satellite), обеспечивая независимость от источников данных.
¶Преимущества и недостатки
¶Преимущества
- Стабильность: не зависят от изменений бизнес-логики. Смена фамилии сотрудника или номера паспорта не требует обновления ключей во всех связанных таблицах.
- Производительность: целочисленные ключи быстрее индексируются и сравниваются, чем строковые или составные ключи. Это ускоряет операции JOIN и поиск.
- Простота: один атрибут вместо нескольких упрощает структуру таблиц, написание запросов и создание внешних ключей.
- Гибкость: можно использовать в распределённых системах (GUID) без риска коллизий.
¶Недостатки
- Дополнительное место: суррогатный ключ занимает место в таблице и индексах, особенно если это GUID (16 байт против 4 байт для INT).
- Потеря семантики: по ключу нельзя понять, что представляет собой запись. Для отладки или ручного анализа данных приходится обращаться к другим полям.
- Сложность миграции: при переносе данных между системами (например, из тестовой среды в продуктивную) автоинкрементные ключи могут конфликтовать, если счётчики не синхронизированы.
- Риск избыточности: если естественный ключ уже является простым и стабильным (например, номер заказа в системе, где он никогда не меняется), добавление суррогатного ключа может быть излишним и усложнять модель.
¶Сравнение с естественным ключом
| Характеристика | Суррогатный ключ | Естественный ключ |
|---|---|---|
| Источник | Создаётся системой | Из данных предметной области |
| Семантика | Отсутствует | Присутствует (например, ИНН) |
| Изменяемость | Неизменяем | Может меняться |
| Размер | Обычно 4–16 байт | Может быть большим (строка, составной) |
| Зависимость от бизнеса | Нет | Да |
| Пример | id = 12345 | passport_series = '45 12', passport_number = '345678' |
¶Критика
Некоторые специалисты по проектированию баз данных (например, Кристофер Дейт) критикуют суррогатные ключи за то, что они нарушают принцип реляционной модели, согласно которому каждая запись должна быть уникально идентифицирована своими данными, а не искусственным номером. Суррогатный ключ, по их мнению, вводит избыточность и может скрывать проблемы с качеством данных (например, дубликаты записей, которые не были обнаружены из-за разных суррогатных ключей). Однако на практике большинство проектировщиков признают суррогатные ключи полезным инструментом, особенно в системах, где естественные ключи нестабильны или сложны.
¶Интересные факты
- В некоторых СУБД (например, Oracle) суррогатные ключи традиционно реализуются через последовательности (sequences), а не через автоинкрементные поля, что даёт больше контроля.
- В PostgreSQL для генерации суррогатных ключей рекомендуется использовать тип
SERIALилиBIGSERIAL, а для UUID — расширениеuuid-osspилиpgcrypto. - В Microsoft SQL Server тип
uniqueidentifier(GUID) может быть сгенерирован функциейNEWID()(случайный) илиNEWSEQUENTIALID()(последовательный, для лучшей производительности индексов). - В распределённых системах (например, в Cassandra) суррогатные ключи могут быть составными (partition key + clustering key), что позволяет эффективно распределять данные по узлам.
¶Источники
- Кодд, Э. Ф. (1979). «Extending the Database Relational Model to Capture More Meaning». ACM Transactions on Database Systems.
- Дейт, К. Дж. (2004). «Введение в системы баз данных», 8-е издание.
- Роб, П., Коронел, К. (2007). «Системы баз данных: проектирование, реализация и управление», 8-е издание.
- Документация PostgreSQL (версия 16): «Глава 8. Типы данных — Числовые типы».
- Документация Microsoft SQL Server (2022): «Типы данных uniqueidentifier и identity».
- Кимбалл, Р. (2013). «The Data Warehouse Toolkit: The Definitive Guide to Dimensional Modeling», 3-е издание.
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →


