Первичный ключ
Первичный ключ (англ. primary key) — это в реляционной модели данных одно или несколько полей (атрибутов) таблицы, значения которых уникально идентифицируют каждую запись (кортеж) в данной таблице. Первичный ключ является фундаментальным понятием теории баз данных и обеспечивает целостность данных на уровне сущности, гарантируя отсутствие дубликатов и позволяя ссылаться на конкретную запись из других таблиц.
Основные свойства
Первичный ключ должен удовлетворять следующим обязательным свойствам:
- Уникальность — значения ключа не могут повторяться в разных записях таблицы. Для каждой строки существует только одно значение первичного ключа.
- Минимальность (неизбыточность) — если ключ состоит из нескольких полей (составной ключ), ни одно из них не должно быть лишним: удаление любого поля нарушает свойство уникальности.
- Стабильность (неизменяемость) — значение первичного ключа после его присвоения записи не должно изменяться в течение всего жизненного цикла этой записи. Изменение может привести к нарушению ссылочной целостности.
- Ненулевое значение (NOT NULL) — ни одно поле, входящее в состав первичного ключа, не может содержать NULL-значение. Отсутствие данных в ключевом поле недопустимо.
- Обязательность — каждая таблица должна иметь первичный ключ (рекомендация теории и практики; в некоторых реализациях СУБД технически возможно создать таблицу без него, но это считается нарушением нормальной формы).
В реляционных базах данных эти требования формализованы через определение ограничения PRIMARY KEY, которое автоматически создаёт уникальный индекс на указанных полях и накладывает ограничение NOT NULL.
Типы первичных ключей
По числу полей
- Простой (простой) ключ — состоит из одного поля (например,
IDв таблице пользователей). - Составной (композитный) ключ — включает два или более полей. Используется, когда ни одно отдельно взятое поле не может гарантировать уникальность записи. Например, для таблицы
Оценкис полямиID_студента,ID_предметаиДатапервичный ключ может быть составным из первых двух полей (при условии, что студент не может получить две оценки в один день).
По происхождению
- Суррогатный ключ — искусственно созданное поле, не имеющее смыслового значения в предметной области. Обычно это автоинкрементное целое число, GUID (глобальный уникальный идентификатор), последовательность или вычисляемый хеш. Пример: поле
IDкакint IDENTITY(1,1). Суррогатный ключ удобен для обеспечения стабильности и неизменности. - Естественный (натуральный) ключ — строится на основе реальных данных, которые уникальны в предметной области. Примеры: табельный номер сотрудника, ИНН, VIN-номер автомобиля, номер паспорта. Использование естественных ключей может вызывать проблемы при изменении этих данных или при их сложной структуре (например, длинные строки).
История и появление термина
Понятие первичного ключа было введено Эдгаром Коддом в 1970 году в его фундаментальной работе «A Relational Model of Data for Large Shared Data Banks». Кодд определил, что для поддержания целостности данных каждая таблица (отношение) должна иметь так называемый «первичный ключ» (primary key), который служит единственным идентификатором кортежа. Идея вытекала из математической теории множеств: в отношении (таблице) не может быть двух одинаковых кортежей, а первичный ключ обеспечивает выполнение этого требования.
В ранних иерархических и сетевых СУБД такой механизм отсутствовал. Реляционная модель сделала первичный ключ частью стандарта, который затем был закреплён в спецификациях SQL (SQL-92, SQL:1999 и последующие).
Реализация в различных СУБД
Стандартный SQL
Синтаксис определения первичного ключа в языке SQL стандартизирован: ``sql CREATE TABLE Employees ( EmployeeID INT PRIMARY KEY, LastName VARCHAR(50) NOT NULL ); ` Или с явным именованием ограничения: `sql CREATE TABLE Employees ( EmployeeID INT, LastName VARCHAR(50) NOT NULL, CONSTRAINT PK_Employees PRIMARY KEY (EmployeeID) ); ``
Особенности популярных СУБД
- MySQL / MariaDB: чаще всего используют автоинкремент (
INT AUTO_INCREMENT). Поддерживается только один первичный ключ на таблицу. Индекс первичного ключа является кластеризованным. - PostgreSQL: использует последовательности (
SERIAL,BIGSERIALилиGENERATED BY DEFAULT AS IDENTITY). Кластеризация необязательна, возможен выбор типа индекса (по умолчанию B-tree). ПоддерживаетсяPRIMARY KEYнад полями с типомUUID. - Oracle: последовательности (
SEQUENCE) вручную связывают с полем, либо используютIDENTITY(с версии Oracle 12c). Первичный ключ автоматически создаёт уникальный индекс, но не делает его кластеризованным (кластеризованный индекс отсутствует как понятие). - Microsoft SQL Server:
IDENTITYдля автоинкремента,UNIQUEIDENTIFIERдля GUID. Кластеризованный индекс по умолчанию создаётся на первичном ключе, но это поведение можно изменить. - SQLite: автоматический
rowidнеявно является первичным ключом, если поле объявлено какINTEGER PRIMARY KEY.
Влияние на производительность
Первичный ключ напрямую влияет на скорость операций поиска, вставки и обновления данных. Поскольку СУБД автоматически создаёт уникальный индекс (обычно B-tree), поиск по значению первичного ключа является одним из самых быстрых видов доступа. Операции WHERE id = 123 выполняются за константное или логарифмическое время (O(log n) для B-tree). При вставке новой записи индекс приходится перестраивать, что может замедлить операции вставки на больших таблицах.
Выбор типа данных для первичного ключа также влияет на производительность. Целочисленные ключи обрабатываются быстрее строковых (особенно Unicode) и UUID. UUID версии 4 (случайные) вызывают высокую фрагментацию кластеризованных индексов, так как они не упорядочены.
Связь с другими ключами
Первичный ключ тесно связан с другими видами ключей в реляционных базах данных:
- Внешний ключ (foreign key) — поле (или набор полей) в дочерней таблице, которое ссылается на первичный ключ родительской таблицы. Обеспечивает ссылочную целостность.
- Альтернативный ключ (alternate key) — поле или набор полей, которые также уникально идентифицируют записи, но не выбраны в качестве первичного. В стандарте SQL такие поля объявляются ограничением
UNIQUE. - Кандидатный ключ (candidate key) — любое поле или набор полей, обладающие свойством уникальности и минимальности. Первичный ключ — один из кандидатных ключей, выбранный разработчиком.
В хорошо спроектированной базе данных все внешние ключи ссылаются на первичные ключи, а не на альтернативные. Это упрощает поддержку целостности.
Проблемы и ограничения
- Изменение естественного ключа — если в качестве первичного ключа используется естественный ключ, его изменение (например, смена номера паспорта) может потребовать каскадного обновления всех внешних ключей, что ресурсоёмко и часто запрещено правилами СУБД.
- Длина ключей — длинные первичные ключи (строки до 256 символов, UUID) замедляют индексацию и увеличивают размер дискового пространства. Особенно критично для составных ключей.
- Необходимость NULL-значений — запрет на NULL в первичном ключе может быть неудобен для таблиц, где часть данных неизвестна. В таких случаях лучше использовать суррогатный ключ.
- Множественные первичные ключи — в одной таблице может быть только один первичный ключ. Это ограничение может быть преодолено добавлением ограничений
UNIQUEна остальные кандидатные ключи.
Интересные факты
- В стандарте SQL сервер может как явно требовать первичный ключ, так и позволять создание таблиц без него. Но большинство реляционных СУБД при создании таблицы с помощью
CREATE TABLEбез первичного ключа не генерирует ошибку, хотя многие рекомендации по проектированию настаивают на его обязательном наличии. - Некоторые СУБД, например, MySQL с движком MyISAM, не поддерживали ограничения ссылочной целостности, и внешние ключи могли ссылаться на обычный индекс, а не обязательно на первичный.
- В проектах, где требуется распределённое создание записей (например, в микросервисной архитектуре или на нескольких серверах), часто используют UUID вместо автоинкрементных целых чисел, так как они могут генерироваться независимо без риска коллизий.
- Термин «суррогатный ключ» часто путают с термином «синтетический ключ» — они синонимы. Однако «синтетический» иногда подчёркивает, что ключ получен искусственно, а не взят из данных.
Источники
- Codd, E. F. (1970). «A Relational Model of Data for Large Shared Data Banks». Communications of the ACM, 13(6), 377–387.
- ISO/IEC 9075-1:2016 — Information technology — Database languages — SQL — Part 1: Framework (SQL/Framework).
- Date, C. J. (2003). «An Introduction to Database Systems». 8th Edition. Addison-Wesley.
- Elmasri, R., Navathe, S. B. (2016). «Fundamentals of Database Systems». 7th Edition. Pearson.
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →