← Назад к вопросам

Что такое Primary Key?

1.2 Junior🔥 201 комментариев
#Базы данных и SQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Primary Key (Первичный ключ)

Primary Key — это один или несколько столбцов таблицы, которые уникально идентифицируют каждую строку в таблице. Это фундаментальная концепция в реляционных базах данных.

Основные свойства Primary Key

  1. Уникальность — каждое значение встречается только один раз в таблице
  2. Не NULL — значение первичного ключа всегда должно быть заполнено
  3. Неизменяемость — в идеале PK не должен изменяться
  4. Минимальность — используется минимально необходимое количество столбцов
  5. Однозначность — каждой строке соответствует ровно один 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)
  • Медленнее индексирование

Правила проектирования

  1. Каждая таблица должна иметь PK — это гарантирует идентичность строк

  2. Выбирай простой surrogate key — обычно целое число, генерируемое БД

  3. Добавляй UNIQUE индекс на Natural Key — если он есть:

CREATE TABLE users (
    id BIGINT PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL,  -- Natural key
    name VARCHAR(255)
);
  1. Избегай составных ключей — используй, только если действительно необходимо

  2. Не меняй 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 — это фундамент хорошей схемы БД, обеспечивающий уникальность, целостность и производительность.