Самоучитель: динамические веб-приложения
Глава 8 из 18IV. Данные и MySQL100 минут

Глава 8. SQL, который остаётся понятным под нагрузкой

Запрос сначала должен выражать точный набор данных, затем получить измеримый план выполнения; индекс строится под условие и порядок, а не для каждой колонки.

После главы вы сможете
  • читать запрос как преобразование
  • объяснить составной индекс
  • увидеть цену пагинации

Сначала форма результата

Перечислите нужные колонки и зерно результата: одна строка на задачу, проект или пользователя. После JOIN число строк может измениться, поэтому SELECT * скрывает и смысл, и стоимость. Явный список колонок предотвращает конфликт одинаковых имён и уменьшает передачу ненужных данных.

WHERE фильтрует строки до группировки, HAVING — группы после агрегирования. Разделение важно не только для синтаксиса: оно показывает, какой набор существует на каждом этапе.

JOIN — утверждение о связи

INNER JOIN оставляет совпавшие пары; LEFT JOIN сохраняет левую строку даже без соответствия. Условие связи пишите в ON, а фильтр результата — в WHERE, иначе незаметно изменится семантика внешнего соединения.

Если JOIN неожиданно умножает строки, проверьте кардинальность связи. DISTINCT способен скрыть симптом, но не объясняет, почему одна предметная сущность появилась несколько раз.

Составной индекс

Индекс упорядочивает ключи и хранит ссылку на строку. Для запроса WHERE project_id = ? AND status = ? ORDER BY created_at DESC полезен индекс, начинающийся с колонок равенства и продолжающийся порядком. Левый префикс определяет, какие варианты запроса смогут его использовать.

Каждый индекс ускоряет некоторые чтения, но увеличивает размер и стоимость записи. Удаляйте дублирующие индексы только после измерения реальной нагрузки и планов.

EXPLAIN как гипотеза

Проверка запросаПлан оценивают вместе с распределением данных и измерением, а не по одному слову в выводе.SQLнамерениеEXPLAINпланДанныекардинальностьМетрикавремя/rows
План оценивают вместе с распределением данных и измерением, а не по одному слову в выводе.

Пагинация и устойчивый порядок

OFFSET прост и подходит для небольших административных списков, но база всё равно проходит пропущенные строки, а вставки сдвигают страницы. Для длинной ленты используйте keyset: условие продолжает выборку после пары created_at и id, совпадающей с ORDER BY.

Порядок должен быть детерминирован. Если несколько строк имеют одинаковую дату, добавьте уникальный id последним ключом сортировки и курсора.

Динамический SQL

Параметры PDO заменяют только значения. Имя колонки и направление сортировки выбираются из allowlist и добавляются как заранее известный фрагмент. Нельзя пытаться передать ORDER BY :field и ожидать, что драйвер превратит строку в идентификатор.

Лимит также проверяйте числом и ограничивайте сверху. Пустой фильтр не должен случайно запускать тяжёлый экспорт всей таблицы.

Практика главы

Напишите запрос списка открытых задач проекта с именем ответственного и курсором. Предложите индекс, затем объясните порядок его колонок и проверку через EXPLAIN.

Локальный прогресс

Закрепите материал

Отметка, заметка, чек-лист и ответы остаются в localStorage этого браузера и не отправляются в аналитику.

Перелинковка со справочником

Проверка актуальности

  • dev.mysql.comhttps://dev.mysql.com/doc/refman/8.4/en/Первичный источник для актуализации фактов. Адрес приведён как текст и не является активной ссылкой.

Текст и схемы созданы для этого самоучителя без воспроизведения страниц, иллюстраций и листингов приложенной книги. Проверено: .

Данные этого сервиса

Настройки cookie и локальных данных

Аналитика

Текущий статус: не выбран. До согласия обе аналитические системы не загружаются.

Локальные данные

Удаление затрагивает только ключи PHP-сервиса в этом браузере и требует подтверждения.

Политики

Политика конфиденциальности · Политика использования файлов cookie