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

Обязательно ли поля в индексе должны быть уникальными в таблице в БД?

1.8 Middle🔥 151 комментариев
#Базы данных и SQL

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

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

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

Индексы и уникальность в БД

Краткий ответ

Нет, поля в индексе НЕ обязательно должны быть уникальными. Индексы делятся на два типа: unique индексы (уникальные ключи) и non-unique индексы (обычные индексы). Большинство индексов в реальных приложениях - это non-unique индексы.

Два типа индексов

1. Non-Unique индекс (обычный индекс)

Позволяет одинаковые значения и используется для ускорения поиска:

CREATE TABLE users (
    id BIGINT PRIMARY KEY,
    name VARCHAR(100),
    status VARCHAR(50),
    created_at TIMESTAMP
);

-- Создаём обычный индекс по status
CREATE INDEX idx_users_status ON users(status);

-- Много пользователей могут иметь status = "ACTIVE"
SELECT * FROM users WHERE status = "ACTIVE";

2. Unique индекс (уникальный индекс)

Гарантирует уникальность значений:

-- Уникальный индекс по email
CREATE UNIQUE INDEX idx_users_email ON users(email);

-- PRIMARY KEY - это тоже UNIQUE индекс
ALTER TABLE users ADD CONSTRAINT pk_users PRIMARY KEY (id);

Составные индексы (Composite Index)

Индекс может содержать несколько полей, и они не должны быть уникальными:

-- Composite non-unique индекс
CREATE INDEX idx_users_status_created 
  ON users(status, created_at);

-- Запрос будет быстрым
SELECT * FROM users 
WHERE status = "ACTIVE" 
  AND created_at > "2024-01-01";

Порядок полей в индексе

Порядок ОЧЕНЬ важен для составных индексов:

-- ✅ Хорошо: status первый (наиболее селективный)
CREATE INDEX idx_orders_status_date 
  ON orders(status, created_at);

-- ❌ Плохо: дата первой (много значений, малая селективность)
CREATE INDEX idx_orders_date_status 
  ON orders(created_at, status);

-- Это объясняется "левым префиксом" (leftmost prefix rule)
-- Индекс (A, B, C) может использоваться для:
-- - WHERE A = ...
-- - WHERE A = ... AND B = ...
-- - WHERE A = ... AND B = ... AND C = ...
-- НО НЕ для WHERE B = ... или WHERE C = ...

Когда использовать индексы

СценарийТип индексаПример
Очень частый поискNon-uniqueИндекс по status, email
СортировкаNon-uniqueИндекс по created_at
Уникальное полеUniqueemail, username
Foreign KeyNon-uniqueИндекс по user_id
Первичный ключUniquePRIMARY KEY

Практический пример Java + SQL

// Entity в JPA
@Entity
@Table(name = "users", indexes = {
    @Index(name = "idx_status", columnList = "status", unique = false),
    @Index(name = "idx_email", columnList = "email", unique = true),
    @Index(name = "idx_status_created", columnList = "status, created_at")
})
public class User {
    @Id
    private Long id;
    
    @Column(unique = true)
    private String email;
    
    private String status;
    
    private LocalDateTime createdAt;
}

// Репозиторий
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    // Будет использован idx_status
    List<User> findByStatus(String status);
    
    // Будет использован idx_email
    Optional<User> findByEmail(String email);
    
    // Будет использован idx_status_created
    @Query("SELECT u FROM User u WHERE u.status = :status AND u.createdAt > :date")
    List<User> findActiveUsers(@Param("status") String status, 
                               @Param("date") LocalDateTime date);
}

Важные правила

  1. Не создавай индекс на каждое поле - это замедлит INSERT, UPDATE, DELETE
  2. Выбирай селективные колонки - индекс на status (2 значения) лучше, чем на gender (2 значения)
  3. Следи за EXPLAIN PLAN - проверяй, используется ли индекс
  4. Composite индексы экономят место - вместо 3 отдельных индексов создай 1 составной
  5. Unique не ускоряет поиск - это просто ограничение целостности данных

EXPLAIN PLAN в PostgreSQL

-- Проверим, используется ли индекс
EXPLAIN ANALYZE
SELECT * FROM users WHERE status = "ACTIVE";

-- Если видишь "Index Scan" - отлично!
-- Если видишь "Seq Scan" - индекс не помогает

Вывод

Индексы - это балансирование между скоростью чтения и стоимостью записи. Unique - это лишь ограничение целостности, не связанное с производительностью индекса.

Обязательно ли поля в индексе должны быть уникальными в таблице в БД? | PrepBro