Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Типы полей, на которые не нужны индексы
Отличный вопрос о производительности БД. Есть поля, на которые индексы неэффективны или вредны:
1. Поля с низкой кардинальностью
Кардинальность — количество уникальных значений в поле. Если значений мало, индекс не поможет:
-- Плохо: только 2 уникальных значения (True/False)
CREATE INDEX idx_is_active ON users(is_active);
-- Лучше: без индекса, СУБД сама выберет оптимальную стратегию
SELECT * FROM users WHERE is_active = true; -- Full table scan может быть быстрее
Примеры полей с низкой кардинальностью:
- Булевы поля (true/false)
- Поля со статусом ("draft", "published", "archived")
- Пол ("M", "F")
- Флаги и метки
2. Небольшие текстовые поля
На короткие VARCHAR индекс часто не дает выигрыша:
-- Сомнительно
CREATE INDEX idx_gender ON users(gender); -- Поле с 2-3 значениями
-- Тем более на очень коротких полях
CREATE INDEX idx_country_code ON users(country_code); -- 2-3 символа
Полный scan таблицы может быть быстрее чем обход индекса.
3. Большие текстовые поля без специальных индексов
Обычные B-tree индексы неэффективны для больших текстов:
-- Плохо: обычный индекс не поможет
CREATE INDEX idx_description ON products(description); -- TEXT или LONGTEXT
-- Хорошо: используем FULLTEXT индекс
CREATE FULLTEXT INDEX idx_description_ft ON products(description);
SELECT * FROM products WHERE MATCH(description) AGAINST('keyword');
4. Поля, которые редко используются в WHERE
Если поле почти никогда не используется в условиях поиска:
# Модель
class Article:
id = Column(Integer, primary_key=True)
title = Column(String, index=True) # Часто ищут по заголовку
content = Column(Text) # Редко ищут по содержимому
views_count = Column(Integer) # Просто число для отображения
created_at = Column(DateTime, index=True) # Часто фильтруют по дате
5. Поля с частыми INSERT/UPDATE
Индексы нужно обновлять при каждой вставке. Если вставок больше чем чтений:
-- Может быть неэффективно, если очень много вставок
CREATE INDEX idx_temp_flag ON logs(is_temp);
-- Логи с множеством вставок, минимум чтений
INSERT INTO logs (message, is_temp) VALUES ('...', true); -- Частая операция
INSERT INTO logs (message, is_temp) VALUES ('...', true);
INSERT INTO logs (message, is_temp) VALUES ('...', true);
6. BLOB и бинарные данные
Лучше не индексировать бинарные и очень большие данные:
-- Не нужен индекс
CREATE TABLE files (
id INT PRIMARY KEY,
name VARCHAR(255) INDEX, -- По имени — окей
content LONGBLOB -- Индекс тут бесполезен
);
7. JSON поля (осторожно)
Обычный индекс на JSON малоэффективен:
-- Неправильно
CREATE INDEX idx_metadata ON users(metadata); -- JSON
-- Правильно (если нужно)
CREATE INDEX idx_metadata_type
ON users((JSON_EXTRACT(metadata, '$.type')));
8. Вычисляемые поля (которые редко фильтруют)
-- Не нужен индекс
CREATE TABLE orders (
id INT PRIMARY KEY,
price DECIMAL,
quantity INT,
total DECIMAL GENERATED ALWAYS AS (price * quantity) -- Без индекса
);
Практический пример для Python проекта
from sqlalchemy import Column, Integer, String, DateTime, Boolean, Index
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
# Индексируем: часто ищут пользователей по email
email = Column(String(255), unique=True, index=True)
# Индексируем: часто сортируют по дате создания
created_at = Column(DateTime, index=True)
# Индексируем: фильтруют по организации
organization_id = Column(Integer, index=True)
# НЕ индексируем: низкая кардинальность (true/false)
is_active = Column(Boolean) # Нет индекса
# НЕ индексируем: редко используется в WHERE
phone = Column(String(20)) # Нет индекса
# НЕ индексируем: большой текст
bio = Column(String(1000)) # Нет индекса
Правило: когда писать индекс
Пиши индекс если:
- Поле часто используется в WHERE, JOIN, ORDER BY
- Высокая кардинальность (много уникальных значений)
- Больше SELECTов чем INSERTs/UPDATEs
Не пиши индекс если:
- Низкая кардинальность (< 10 уникальных значений)
- Поле редко в условиях
- Огромный текст (нужен FULLTEXT)
- Много вставок, мало чтений
Проверка эффективности индекса
-- PostgreSQL: посмотреть использованные индексы
EXPLAIN ANALYZE SELECT * FROM users WHERE is_active = true;
-- Если видишь "Seq Scan" вместо "Index Scan", индекс не помог
Вывод
Не пиши индексы на:
- Низкокардинальные поля
- Редко используемые в WHERE
- Большие текстовые поля
- Часто обновляемые поля с редкими чтениями
- Булевы и флаги
Лучше начать без индексов, потом добавлять по результатам профилирования.