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

Какую стратегию генерации ID рекомендуют использовать?

2.0 Middle🔥 181 комментариев
#ORM и Hibernate#Базы данных и SQL

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

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

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

Стратегии генерации ID

Выбор стратегии генерации ID - важное архитектурное решение. Разные стратегии подходят для разных сценариев. Давайте разберём основные подходы.

1. AUTO INCREMENT (Serial)

Даёт базе данных автоматически генерировать ID:

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;  // 1, 2, 3, ...
    
    private String email;
}

В SQL:

CREATE TABLE users (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    email VARCHAR(255) NOT NULL
);

Плюсы:

  • Простота реализации
  • Компактное хранение (числа)
  • Быстрые индексы
  • Последовательные ID удобны для пагинации

Минусы:

  • Плохо масштабируется при шардировании
  • Раскрывает информацию о количестве записей
  • В распределённых системах нужна координация
  • Конфликты при репликации

2. UUID (Universally Unique Identifier)

Уникальные идентификаторы, генерируемые на приложении:

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.UUID)
    private UUID id;  // "f47ac10b-58cc-4372-a567-0e02b2c3d479"
    
    private String email;
}

Или явно:

public User createUser(String email) {
    User user = new User();
    user.setId(UUID.randomUUID());
    user.setEmail(email);
    return user;
}

Плюсы:

  • Уникален везде (не нужна база)
  • Отлично масштабируется при шардировании
  • Не раскрывает информацию
  • Легко генерировать на стороне клиента

Минусы:

  • Больше памяти (16 байт vs 8 для Long)
  • Медленнее индексирование
  • Менее читаемы (нужно копировать)
  • Индексы занимают больше места
STORAGE SIZE COMPARISON:
Long:   8 bytes    (1, 2, 3, ...)
UUID:  16 bytes    (f47ac10b-58cc-...)

3. SEQUENCE (Для PostgreSQL)

@Entity
public class User {
    @Id
    @GeneratedValue(
        strategy = GenerationType.SEQUENCE,
        generator = "user_seq"
    )
    @SequenceGenerator(
        name = "user_seq",
        sequenceName = "user_id_seq",
        allocationSize = 1
    )
    private Long id;
    
    private String email;
}

В SQL:

CREATE SEQUENCE user_id_seq START 1 INCREMENT 1;

CREATE TABLE users (
    id BIGINT PRIMARY KEY DEFAULT nextval('user_id_seq'),
    email VARCHAR(255) NOT NULL
);

Плюсы:

  • Работает хорошо в PostgreSQL
  • Больше контроля чем IDENTITY
  • Можно настроить шаг (allocationSize)

Минусы:

  • Зависит от БД
  • Меньше контроля в распределённых системах

4. Distributed ID (Snowflake, Ulid)

Для высоконагруженных распределённых систем:

// Snowflake ID (Twitter алгоритм)
public class SnowflakeIdGenerator {
    private static final long EPOCH = 1609459200000L;  // 2021-01-01
    private static final int DATACENTER_ID = 1;
    private static final int WORKER_ID = 1;
    private long sequence = 0;
    
    public synchronized long generate() {
        long timestamp = System.currentTimeMillis() - EPOCH;
        long id = (timestamp << 22) 
            | (DATACENTER_ID << 17) 
            | (WORKER_ID << 12) 
            | (sequence++ & 0xFFF);
        return id;
    }
}

// Использование
@Entity
public class Order {
    @Id
    private Long id;  // Snowflake ID
    
    private String productName;
}

@Service
public class OrderService {
    private final SnowflakeIdGenerator idGen;
    
    public Order createOrder(String productName) {
        Order order = new Order();
        order.setId(idGen.generate());
        order.setProductName(productName);
        return order;
    }
}

Плюсы:

  • Глобально уникальны
  • Отлично масштабируются
  • Компактнее UUID (8 байт vs 16)
  • Содержат timestamp
  • Работают без синхронизации

Минусы:

  • Сложнее реализовать
  • Требуют clock sync между сервисами
  • Менее читаемы

5. ULID (Universally Unique Lexicographically Sortable Identifiers)

import com.github.f4b6a3.ulid.UlidFactory;

@Entity
public class User {
    @Id
    private String id;  // "01ARZ3NDEKTSV4RRFFQ69G5FAV"
    
    private String email;
}

@Service
public class UserService {
    public User createUser(String email) {
        User user = new User();
        user.setId(UlidFactory.getDefaultFactory().create().toString());
        user.setEmail(email);
        return user;
    }
}

Плюсы:

  • Уникальны везде
  • Отсортированы по времени (sortable)
  • Более компактны чем UUID (26 символов)
  • Легко читаются людям
  • Содержат timestamp

Минусы:

  • Строки (медленнее индексирование)
  • Требуют библиотеку
  • Меньше известны

6. Хибернейт Identity Generator

@Entity
public class User {
    @Id
    @GeneratedValue(
        strategy = GenerationType.SEQUENCE,
        generator = "user_gen"
    )
    @GenericGenerator(
        name = "user_gen",
        strategy = "org.hibernate.id.UUIDGenerator"
    )
    private UUID id;
    
    private String email;
}

Сравнительная таблица

СтратегияРазмерМасштабируемостьЧитаемостьИспользование
IDENTITY8 byteПлохоХорошоSingle DB
UUID16 byteОтличноПлохоМикросервисы
SEQUENCE8 byteСреднееХорошоPostgreSQL
Snowflake8 byteОтличноСреднееHigh Load
ULID26 charОтличноХорошоModern Apps

Рекомендации

Выбирайте стратегию в зависимости от контекста:

IDENTITY/SEQUENCE - для однозначных (single database) приложений ✅ UUID - для микросервисов и распределённых систем ✅ Snowflake/ULID - для высоконагруженных распределённых систем ✅ ULID - если нужны отсортированные ID с timestamp

Мой совет

Для новых проектов я рекомендую:

  • Небольшие приложения: IDENTITY (PostgreSQL) или SEQUENCE
  • Микросервисы: UUID или ULID
  • Высоконагруженные системы: Snowflake ID или ULID

У меня есть опыт с всеми этими стратегиями, и я выбираю в зависимости от требований проекта и его масштаба.

Какую стратегию генерации ID рекомендуют использовать? | PrepBro