Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Primary Key (Первичный ключ)
Primary Key — это один или несколько столбцов таблицы, которые уникально идентифицируют каждую строку в таблице. Это фундаментальная концепция в реляционных базах данных.
Основные свойства Primary Key
- Уникальность — каждое значение встречается только один раз в таблице
- Не NULL — значение первичного ключа всегда должно быть заполнено
- Неизменяемость — в идеале PK не должен изменяться
- Минимальность — используется минимально необходимое количество столбцов
- Однозначность — каждой строке соответствует ровно один PK
Простой Primary Key
Простой ключ состоит из одного столбца:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(100)
);
Здесь id — простой первичный ключ. База данных автоматически:
- Генерирует уникальные значения (SERIAL/AUTO_INCREMENT)
- Создаёт индекс для быстрого поиска
- Запрещает NULL и дубликаты
Составной Primary Key
Составной (композитный) ключ состоит из нескольких столбцов:
CREATE TABLE order_items (
order_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT,
price DECIMAL(10, 2),
PRIMARY KEY (order_id, product_id)
);
Здесь комбинация (order_id, product_id) гарантирует, что в одном заказе не будет двух строк для одного товара.
Natural Key vs Surrogate Key
Natural Key — использует существующие данные:
CREATE TABLE products (
sku VARCHAR(50) PRIMARY KEY, -- SKU товара
name VARCHAR(255),
price DECIMAL(10, 2)
);
Преимущества:
- Имеет бизнес-смысл
- Не требует генерации
Недостатки:
- Может измениться (например, SKU переформатирован)
- Часто длинный
Surrogate Key — искусственный идентификатор:
CREATE TABLE products (
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
sku VARCHAR(50) UNIQUE NOT NULL,
name VARCHAR(255),
price DECIMAL(10, 2)
);
Преимущества:
- Никогда не меняется
- Занимает мало места
- Легко использовать в foreign keys
Недостатки:
- Не имеет бизнес-смысла
Primary Key и индексирование
База данных автоматически создаёт индекс на первичный ключ:
-- В PostgreSQL это эквивалентно:
CREATE TABLE users (
id BIGINT PRIMARY KEY,
name VARCHAR(255)
);
-- Автоматически создаётся индекс:
-- CREATE UNIQUE INDEX users_pkey ON users(id);
Индекс позволяет искать строку по PK за O(log n) вместо O(n).
Foreign Key и связи
Primary Key используется для создания связей через Foreign Key:
CREATE TABLE orders (
id BIGINT PRIMARY KEY,
user_id BIGINT NOT NULL,
order_date TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);
Это гарантирует referential integrity — в таблице orders могут быть только user_id, которые существуют в таблице users.
Типы значений для Primary Key
INT/BIGINT — самый распространённый:
CREATE TABLE posts (
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
title VARCHAR(255)
);
UUID — для распределённых систем:
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255)
);
Преимущества UUID:
- Генерируется на клиенте без обращения к БД
- Не раскрывает внутреннюю нумерацию
- Удобен при федерации БД
Недостатки:
- Больше места (16 байт vs 8 для BIGINT)
- Медленнее индексирование
Правила проектирования
-
Каждая таблица должна иметь PK — это гарантирует идентичность строк
-
Выбирай простой surrogate key — обычно целое число, генерируемое БД
-
Добавляй UNIQUE индекс на Natural Key — если он есть:
CREATE TABLE users (
id BIGINT PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL, -- Natural key
name VARCHAR(255)
);
-
Избегай составных ключей — используй, только если действительно необходимо
-
Не меняй PK после создания строки — это нарушает связи
Проверка Primary Key
-- В PostgreSQL
SELECT constraint_name, constraint_type
FROM information_schema.table_constraints
WHERE table_name = users;
-- Результат:
-- users_pkey | PRIMARY KEY
Практический пример
-- Плохо — нет PK
CREATE TABLE logs (
message VARCHAR(1000),
timestamp TIMESTAMP
);
-- Хорошо — есть простой surrogate key
CREATE TABLE logs (
id BIGSERIAL PRIMARY KEY,
message VARCHAR(1000),
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Ещё лучше — добавлен индекс на timestamp для быстрого поиска по времени
CREATE INDEX idx_logs_timestamp ON logs(timestamp);
Производительность
Первичный ключ критичен для производительности:
-- Быстро — ищем по PK (индекс)
SELECT * FROM users WHERE id = 42; -- O(log n)
-- Медленно — полный скан таблицы
SELECT * FROM users WHERE name = John; -- O(n)
Вывод: Primary Key — это фундамент хорошей схемы БД, обеспечивающий уникальность, целостность и производительность.