Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI21 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Индекс с условием (Partial Index / Conditional Index)
Индекс с условием — это индекс БД, который индексирует только строки, удовлетворяющие определённому условию WHERE. Это мощная оптимизация для таблиц с большим количеством данных, где нужно часто искать по подмножеству.
Зачем это нужно
- Экономия места — индекс занимает меньше памяти, так как содержит только релевантные данные
- Быстрее обновления — когда мы добавляем/изменяем данные, индекс обновляется меньше
- Лучше производительность — для отфильтрованных запросов работает значительно быстрее
- Уменьшение fragmentation — индекс более компактный
SQL синтаксис (PostgreSQL)
-- Обычный индекс
CREATE INDEX idx_users_deleted ON users(id);
-- Индекс с условием — индексируем только активных пользователей
CREATE INDEX idx_users_active ON users(id)
WHERE is_deleted = false;
-- Индекс для часто используемого фильтра
CREATE INDEX idx_orders_pending ON orders(created_at)
WHERE status = 'pending';
-- Комплексное условие
CREATE INDEX idx_premium_users ON users(email)
WHERE subscription_plan = 'premium'
AND is_active = true
AND created_at > NOW() - INTERVAL '1 year';
Практический пример
-- Таблица с 100 млн мягких удалений (soft deletes)
CREATE TABLE posts (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL,
title VARCHAR(255),
is_deleted BOOLEAN DEFAULT false,
created_at TIMESTAMPTZ
);
-- БЕЗ частичного индекса
CREATE INDEX idx_posts_user ON posts(user_id);
-- Размер: ~5 GB (индексирует все 100 млн строк)
-- С частичным индексом
CREATE INDEX idx_posts_user_active ON posts(user_id)
WHERE is_deleted = false;
-- Размер: ~1 GB (индексирует только активные посты, скажем 20%)
-- Запрос использует индекс
SELECT * FROM posts
WHERE user_id = 42 AND is_deleted = false;
-- Query planner автоматически использует idx_posts_user_active
Django ORM синтаксис
from django.db import models
from django.db.models import Q, Index
class Post(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=255)
is_deleted = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
indexes = [
# Обычный индекс
Index(fields=['user_id']),
# Частичный индекс — только активные посты
Index(
fields=['user_id'],
condition=Q(is_deleted=False),
name='idx_posts_user_active'
),
# Для часто используемых фильтров
Index(
fields=['user_id', 'created_at'],
condition=Q(is_deleted=False),
name='idx_posts_user_created'
),
]
SQLAlchemy синтаксис
from sqlalchemy import Column, Index, Boolean, String, ForeignKey
from sqlalchemy.orm import declarative_base
Base = declarative_base()
class Post(Base):
__tablename__ = 'posts'
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey('users.id'))
title = Column(String(255))
is_deleted = Column(Boolean, default=False)
created_at = Column(DateTime(timezone=True))
# Частичный индекс через DDL
__table_args__ = (
Index(
'idx_posts_user_active',
user_id,
postgresql_where=is_deleted == False
),
)
Когда использовать
✅ Используй частичный индекс:
- Soft delete паттерн (много деактивированных записей)
- Фильтр по статусу (большая часть в одном статусе)
- Временные данные (old data vs current)
- Логические флаги (архивировано, одобрено и т.п.)
❌ Не используй:
- На маленьких таблицах (< 100k строк)
- Если условие не стабильно (постоянно меняется)
- Если много условий (раньше создай отдельный индекс)
Проверка использования индекса
-- PostgreSQL — посмотреть план запроса
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM posts
WHERE user_id = 42 AND is_deleted = false;
-- Результат показывает, какой индекс использован
-- Index Scan using idx_posts_user_active on posts (cost=0.42..2.14)
Важные моменты
- Условие в индексе предикат-зависимо — запрос должен точно совпадать с условием
- Частичный индекс требует поддержки БД (PostgreSQL, SQLite поддерживают, MySQL ограниченно)
- Не забывай об индексах при миграциях — update миграции с
CREATE INDEX CONCURRENTLYна production
Это мощный инструмент для оптимизации БД, особенно при работе с soft deletes и логическими флагами.