Здравствуй, дорогой читатель. Сегодня Автор предлагает поговорить о штуке, которую обычный человек почти никогда не видит, но каждый день благодарит, сам того не зная. Вы открываете интернет-магазин, вводите «синие кроссовки 42 размер», и сайт находит нужное почти мгновенно. Вы ищете письмо за прошлый год — почта отвечает за секунду. Вы смотрите историю заказов — приложение не уходит думать на обед.
А ведь где-то там лежат миллионы записей.
Почему компьютер не перебирает их по одной, как человек, который потерял квитанцию в ящике с бумагами?
Сегодня разбираемся с индексами в базах данных. Без скучных схем, но с Алисой, Ильёй, Ариной и коробкой рисунков.
Начнём с обычной сцены
Представьте, что у Алисы, Ильи и Арины есть большая семейная коробка с рисунками.
Там всё подряд:
- рисунки Алисы с домиками;
- схемы Ильи с роботами;
- отпечатки ладошек Арины;
- открытки от бабушки;
- старые фотографии;
- записки «не забыть купить молоко».
Сначала коробка маленькая, и проблем нет. Алиса спрашивает:
— Илья, где мой рисунок с красной машиной?
Илья открывает коробку, перебирает десять листов и быстро находит.
Но проходит год. Потом ещё один. Коробок становится пять. Потом десять. Арина взрослеет и производит рисунки с такой скоростью, будто у неё внутри маленькая типография.
Теперь Алиса снова спрашивает:
— Где мой рисунок с красной машиной?
Илья молча смотрит на гору бумаги.
— Алиса, если я буду искать руками, мы встретим Новый год прямо здесь.
Вот в этот момент рождается идея индекса.
Что такое индекс
Илья берёт отдельный блокнот и пишет:
- «красная машина» — коробка 3, папка «транспорт», лист 12;
- «домик у моря» — коробка 1, папка «лето», лист 4;
- «робот с антеннами» — коробка 5, папка «Илья», лист 27;
- «рисунок Арины с непонятным пятном» — коробка 2, папка «лучше не спрашивать», лист 8.
Теперь, когда Алиса ищет красную машину, Илья не перерывает все коробки. Он открывает блокнот, находит строку и сразу идёт в нужное место.
Если совсем просто: индекс в базе данных — это вспомогательная структура, которая помогает быстро находить нужные записи, не просматривая всю таблицу целиком.
Таблица — это коробки с рисунками.
Индекс — это блокнот, где написано, где что лежит.
Запрос — это просьба Алисы: «Найди мне вот это».
Как поиск работает без индекса
Допустим, в базе есть таблица заказов интернет-магазина.
В ней миллион строк:
- номер заказа;
- имя покупателя;
- дата;
- товар;
- сумма;
- статус доставки.
Алиса открывает приложение и хочет увидеть свои заказы.
Если индекса нет, база данных может сделать самый прямолинейный вариант: пройти по всей таблице от первой строки до последней и проверить каждую:
«Это заказ Алисы? Нет. Это? Нет. Это? Нет. А вот это да. Запомним. Идём дальше».
Такой поиск называется полным просмотром таблицы. На английском часто говорят full table scan.
Для маленькой таблицы это нормально. Если у вас двадцать заказов, можно и глазами посмотреть. Но если заказов десять миллионов, такой подход превращается в поход по складу с фонариком.
База данных, конечно, быстрая. Но даже быстрая машина не любит делать лишнюю работу.
Как поиск работает с индексом
Теперь представим, что у таблицы заказов есть индекс по полю «покупатель».
Это как отдельная картотека:
- Алиса — строки 15, 203, 8041;
- Илья — строки 7, 900, 901;
- бабушка — строки 44, 45, 46;
- Почтальон — строки 1024, 2048.
Когда Алиса просит свои заказы, база сначала смотрит в индекс. Индекс говорит: «Алиса лежит вот здесь, вот здесь и вот здесь». База сразу идёт к нужным строкам.
Разница примерно такая:
- без индекса: обойти весь дом и заглянуть в каждый ящик;
- с индексом: открыть список и сразу пойти к нужной полке.
Именно поэтому поиск по хорошо подобранному индексу может быть быстрее в десятки, сотни и тысячи раз.
Почему тогда не сделать индекс на всё?
Вот тут Алиса задаёт очень правильный вопрос:
— Илья, если блокнот такой полезный, давай заведём блокнот на всё. По цвету, по дате, по размеру, по настроению, по количеству пятен от Арины.
Илья вздыхает.
— Можно. Только потом мы будем жить не в комнате, а внутри блокнотов.
Индексы ускоряют чтение, но не бесплатны.
Во-первых, они занимают место. Блокнот тоже где-то лежит. В базе данных индекс может занимать заметный объём на диске.
Во-вторых, индекс нужно обновлять. Если Алиса добавила новый рисунок, Илья должен положить лист в коробку и записать его в блокнот. Если рисунок переехал, запись нужно поправить. Если рисунок удалили, индекс тоже должен узнать об этом.
В базе данных всё так же. Когда программа вставляет, изменяет или удаляет строку, база обновляет не только саму таблицу, но и связанные индексы.
Поэтому слишком много индексов может замедлить запись.
Индекс — это не волшебная кнопка «сделать быстро». Это обмен: быстрее искать, но дороже хранить и обновлять.
Какие поля обычно индексируют
Автор не будет превращать статью в инструкцию администратора баз данных, но общий смысл полезен.
Индексы часто делают по полям, по которым часто ищут, сортируют или связывают таблицы.
Например:
- email пользователя;
- номер заказа;
- дата создания;
- статус заявки;
- id пользователя;
- артикул товара;
- номер телефона;
- внешний ключ, который связывает одну таблицу с другой.
Если интернет-магазин постоянно ищет заказ по номеру, индекс по номеру заказа логичен.
Если приложение часто показывает «все заказы Алисы за последний месяц», может пригодиться индекс по пользователю и дате.
Если поле почти никогда не используется в поиске, индекс на нём может быть лишним.
Это как делать отдельный каталог «рисунки, на которых Арина держала карандаш левой рукой». Забавно, но если никто так не ищет, пользы мало.
Индекс похож на оглавление, но умнее
Хорошая бытовая аналогия — книга.
Если вы ищете главу «Как работает кэш», можно открыть оглавление и сразу перейти на страницу 87. Это индекс в простом виде.
Но база данных часто работает с огромными объёмами, поэтому её индексы устроены хитрее. Один из классических вариантов — дерево. Не дерево в лесу, а структура, где каждый уровень помогает быстро сузить поиск.
Представьте библиотеку:
Сначала вы выбираете шкаф: буквы А-К, Л-Р или С-Я.
Потом полку: Алиса, Андрей, Артём.
Потом папку: Алиса Иванова, Алиса Петрова.
Потом конкретную карточку.
Вы не смотрите все карточки подряд. Вы каждый раз отсекаете большую часть вариантов.
Так работают многие индексы: они позволяют базе быстро прийти к маленькому участку данных вместо того, чтобы идти через всю таблицу.
Почему иногда индекс не помогает
Дорогой читатель, здесь есть важная деталь: наличие индекса ещё не значит, что база всегда им воспользуется.
Представьте, что Алиса спрашивает:
— Найди все рисунки, где есть хоть немного синего цвета.
А синее есть почти везде: небо, море, платье, робот, чашка, случайная линия Арины.
Илья смотрит в блокнот и понимает: по индексу идти бессмысленно. Проще сразу открыть коробки, потому что результат всё равно будет почти весь.
В базе данных похожая ситуация. Если запрос возвращает большую часть таблицы, полный просмотр может быть дешевле, чем прыжки по индексу.
Ещё индекс может не помочь, если запрос написан так, что база не может нормально использовать поле. Например, когда над полем делают сложное преобразование, ищут по слишком размытому условию или индекс создан не под тот сценарий.
Это не значит, что индекс плохой. Это значит, что индекс должен соответствовать реальному вопросу.
Где мы встречаем индексы в жизни
Индексы есть почти везде, где нужно быстро искать.
В интернет-магазине они помогают найти товар по названию, категории, цене и бренду.
В почте — письмо по отправителю, теме или дате.
В банке — операцию по номеру счёта или времени.
В мессенджере — сообщение по чату и дате.
В поиске по сайту — статью по словам.
В базе данных канала — публикацию по названию, дате или ссылке.
Пользователь обычно видит только результат: «О, быстро нашлось». Но внутри почти всегда есть заранее подготовленная дорожка к данным.
Что может пойти не так
Индексы не опасны сами по себе. Но неправильное обращение с ними может испортить жизнь сервису.
Первое: индексов слишком мало. Тогда база постоянно перебирает огромные таблицы и тормозит.
Второе: индексов слишком много. Тогда запись новых данных становится тяжёлой, потому что после каждой вставки нужно обновить целую стопку вспомогательных структур.
Третье: индексы созданы не под те запросы. Это как каталог по цвету бумаги, когда все ищут по имени автора.
Четвёртое: данные изменились. Раньше таблица была маленькой, и всё работало без индексов. Потом проект вырос, и старые решения начали скрипеть.
Поэтому разработчики и администраторы баз данных не просто «добавляют индексы на всякий случай». Они смотрят, какие запросы реальные, что тормозит, как база строит план выполнения и где индекс действительно даст пользу.
Мифы
Миф: индекс всегда ускоряет базу.
На самом деле: индекс ускоряет конкретные виды поиска, сортировки и соединения таблиц. Но он может замедлять вставку и обновление данных.
Миф: чем больше индексов, тем лучше.
На самом деле: слишком много индексов превращает базу в комнату, где каталогов больше, чем самих рисунков.
Миф: индекс — это копия всей таблицы.
На самом деле: индекс хранит не всё подряд, а выбранные значения и ссылки на строки. Хотя в некоторых случаях он может содержать дополнительные данные.
Миф: если сайт тормозит, надо просто добавить индекс.
На самом деле: иногда проблема в запросе, архитектуре, сети, кэше, блокировках или объёме данных. Индекс — сильный инструмент, но не универсальная таблетка.
Итог
Индекс в базе данных — это как картотека Ильи для семейных рисунков.
Без неё приходится перебирать коробки одну за другой. С ней можно быстро понять, где лежит нужный лист.
Главная мысль простая: индекс не хранит смысл данных вместо базы, он помогает быстрее найти дорогу к нужным данным.
Хорошо подобранный индекс делает сервис быстрым и спокойным. Плохо подобранный — занимает место, мешает записи и создаёт иллюзию порядка.
Так что в следующий раз, когда поиск в приложении мгновенно найдёт старый заказ, письмо или фотографию, можно мысленно поблагодарить маленький невидимый блокнот. Где-то в базе данных он тихо делает свою работу.
Подписывайтесь на канал Автора, если хотите и дальше разбирать IT без канцелярита и с нормальными человеческими картинками. В следующий раз можно поговорить о транзакциях: почему в банке операция должна быть «или вся целиком, или никак».
UPD
Для тех, кто хочет чуть глубже, но без погружения в болотистые дебри документации:
- B-tree / B+tree — классический тип индекса в реляционных базах данных. Он помогает быстро искать значения по отсортированной древовидной структуре.
- Hash index — индекс, который хорошо подходит для точного поиска «равно вот этому значению», но обычно хуже помогает с диапазонами вроде «все заказы за май».
- Composite index — составной индекс по нескольким полям, например (user_id, created_at). Полезен, когда запросы часто ищут данные по комбинации признаков.
- Unique index — индекс, который не только ускоряет поиск, но и запрещает дубли. Например, два пользователя не могут иметь один и тот же email.
- Covering index — индекс, в котором уже есть все данные, нужные запросу. Тогда базе иногда не нужно идти в основную таблицу.
- Query planner — часть СУБД, которая решает, как именно выполнить запрос: использовать индекс, просмотреть таблицу целиком, соединить таблицы в одном порядке или в другом.
- Explain plan — способ посмотреть, какой план выбрала база. Это уже инструмент для разработчиков, но идея простая: не гадать, а спросить базу, как она собирается искать.
Автор сознательно не разбирал синтаксис CREATE INDEX, разные реализации PostgreSQL, MySQL и других СУБД, селективность, кардинальность и блокировки при построении индексов. Для первого знакомства достаточно образа: индекс — это умная картотека, а не магия.