Методическое руководство преподавателя
Дисциплина: ОП.08 Основы проектирования баз данных | Тема 3. Этапы проектирования баз данных (§2.2 с.7 программы)
Практическое занятие №8: поиск по одному и нескольким полям (Занятие 20, финал семестра 3, 2 академических часа)
1. Детальный тайминг занятия (основной 80 минут и сокращенный 60 минут)
Занятие 20 завершает учебную программу 3-го семестра. Главная цель — закрепить умение проектировать эффективные поисковые запросы по одному и нескольким полям, сопоставлять физические механизмы поиска СУБД с предикатами запроса и составлять строгий поисковый протокол с анализом времени отклика и планов выполнения.
| Этап занятия | Основной регламент (80 мин) | Сокращенный регламент (60 мин) | Педагогическая задача и содержание этапа |
|---|---|---|---|
| 1. Организационный момент и мотивация | 5 минут | 3 минуты | Приветствие, проверка явки, фиксация статуса завершения 3-го семестра. Озвучивание проблемы: «Почему при миллионе записей сайт падает на обычном поиске по каталогу?». |
| 2. Актуализация опорных знаний | 10 минут | 7 минут | Фронтальный опрос: понятие индекса B-Tree, физический доступ через кучу (Heap), логарифмическая сложность $O(\log N)$ против линейной $O(N)$ при полном сканировании (Sequential Scan). |
| 3. Инструктаж и методический разбор механизмов поиска | 15 минут | 10 минут | Демонстрация преподавателем 4 физических механизмов: точечный поиск по первичному/уникальному ключу, диапазонный поиск (Index Range Scan), сопоставление с шаблоном (LIKE), полнотекстовый поиск (FTS, GIN). |
| 4. Самостоятельная практическая работа студентов | 40 минут | 32 минуты | Студенты работают в интерактивном листе zanyatie.html по 4 вариантам. Составление SQL-запросов, фиксация времени отклика, структуры индексов и заполнение поискового протокола. |
| 5. Защита протоколов, подведение итогов семестра 3 и рефлексия | 10 минут | 8 минут | Критериальный разбор типовых ошибок, выставление баллов в ведомость (шкала 0–4 балла), фиксация итогов освоения Темы 3 и завершения 3 семестра. |
2. Архитектура поисковых механизмов реляционных СУБД
2.1. Точечный поиск по ключу: Index Scan и сложность $O(\log N)$
Точечный поиск по равенству (WHERE primary_key = constant) опирается на классическую древовидную структуру B-Tree (Balanced Tree). В таблице без индекса поиск требует Sequential Scan — чтения всех $M$ дисковых страниц (блоков по 8 КБ в PostgreSQL), что приводит к вычислительной сложности $O(N)$ и катастрофической деградации дискового ввода-вывода (I/O Bottleneck).
Высота сбалансированного дерева $H$ определяется коэффициентом ветвления (Fan-out) $B \approx 200..500$:
H \le \lceil \log_B (N) \rceil + 1
Для таблицы из 20 000 000 записей глубина дерева составляет всего 3–4 уровня. Точечный поиск считывает ровно 3 страницы индекса и 1 страницу кучи таблицы (Heap Page). Время выполнения: < 0.05 миллисекунды.
2.2. Диапазонный поиск: Index Range Scan и горизонтальные связи листьев
Диапазонные предикаты (WHERE column BETWEEN A AND B, >=, <=) эксплуатируют фундаментальное свойство B-Tree: все листовые узлы связаны между собой двусвязным списком в строго отсортированном порядке.
- Фаза 1 (Спуск от корня): Алгоритм за $O(\log N)$ шагов находит листовой блок, содержащий левую границу диапазона $A$.
- Фаза 2 (Листовой проход): СУБД больше не возвращается к корневому или промежуточным узлам. Чтение кортежей выполняется последовательно по указателям листьев вперед до достижения границы $B$.
- Сортировка: Клауза
ORDER BY columnвыполняется без накладных расходов на процессорную сортировку (Elimination of Sort Node), поскольку данные уже поступают в идеальном физическом порядке.
2.3. Сопоставление с шаблоном: оператор LIKE и правило левого префикса
Один из самых коварных разделов проектирования запросов — поиск по строковым маскам:
LIKE 'text%'
СУБД транслирует предикат в диапазон: col >= 'text' AND col < 'texu'. Используется Index Range Scan. Поиск выполняется мгновенно за логарифмическое время.
Важно для PostgreSQL: В локалях non-C индекс B-Tree должен быть создан с операторным классом varchar_pattern_ops!
LIKE '%text%'
B-Tree индекс БЕСПОЛЕЗЕН! Так как первый символ строки неизвестен, маршрутизация по дереву невозможна. СУБД вынуждена запускать полный Seq Scan, считывая терабайты диска.
Инженерное решение: Использование расширения pg_trgm с триграммными индексами GIN или перенос задачи в полнотекстовый поиск.
2.4. Полнотекстовый поиск (FTS): стемминг, стоп-слова и инвертированный индекс GIN
Когда требуется искать слова и фразы в неструктурированных текстах (аннотации книг, описания товаров, история обращений), оператор LIKE терпит крах не только по скорости, но и по смыслу (он не учитывает окончания, падежи и предлоги).
Полнотекстовый поиск в PostgreSQL базируется на трех компонентах:
- Стемминг (Stemming): Морфологический редуктор (Snowball) отсекает окончания и суффиксы, приводя слова к единой нормальной лексеме (например, «базами», «баз», «базе» $\to$ лексема
'баз'). - Словари стоп-слов: Фильтрация частотного языкового шума (предлоги «и», «в», «на», союзы, местоимения), который не несет смысловой нагрузки при поиске.
- Типы данных
tsvectorиtsquery: Документ конвертируется в отсортированный список нормализованных лексем с их позициями (to_tsvector('russian', text)), а поисковый запрос — в булево выражение лексем (to_tsquery('russian', 'база & проект')). Сопоставление выполняется бинарным оператором@@. - Инвертированный индекс GIN (Generalized Inverted Index): В B-Tree ключ — это целая колонка, указывающая на строку. В GIN ключами B-Tree являются отдельные лексемы (слова), а в листьях хранятся отсортированные списки идентификаторов всех строк (Posting Lists), содержащих это слово. Поиск любого сочетания слов выполняется за доли миллисекунды через пересечение битовых карт (Bitmap Index Scan).
3. Составление поискового протокола
Поисковый протокол — это профессиональный отчет инженера баз данных, фиксирующий поведение оптимизатора запросов при различных формах фильтрации. Протокол должен содержать:
- Формулировку бизнес-задачи и точный SQL-предикат секции
WHERE. - Наличие и спецификацию покрывающего индекса (B-Tree составной, Unique, GIN, Partial).
- Ожидаемый узел плана исполнения
EXPLAIN(Seq Scan,Index Scan,Index Only Scan,Bitmap Index Scan,Bitmap Heap Scan). - Метрики производительности: расчетная стоимость (Startup Cost / Total Cost) и реальное время отклика в миллисекундах (Execution Time).
- Анализ селективности: сколько строк отсекается на уровне индекса и сколько строк реально возвращается клиенту.
4. Типовые ошибки студентов и педагогические приемы устранения
Симптом: Студент строит обычный индекс CREATE INDEX ON users(name) и удивляется, почему запрос WHERE name LIKE '%иван%' выполняется 3 секунды и планировщик пишет Seq Scan.
Педагогический прием «Аналогия с телефонным справочником»: Преподаватель просит студента: «Найди мне в бумажном телефонном справочнике абонента, у которого фамилия оканчивается на "...ов". С какой страницы ты начнешь?». Студент осознает, что без знания первой буквы справочник придется перелистывать целиком от корки до корки.
Симптом: Для запроса WHERE region = 'Югра' AND income > 100000 создается индекс (income, region).
Педагогический прием «Иерархия фильтрации»: Разбор на доске. Если первым идет диапазон income > 100000, то все строки с доходами выше 100 тысяч разбросаны по разным регионам. Ветвь region = 'Югра' внутри диапазона не сгруппирована. Правило: Равенство ВСЕГДА ставится левее диапазона!
Симптом: Попытка реализовать поиск по каталогу книг через WHERE title LIKE '%база%', из-за чего книги с названием «Основы реляционных баз данных» не находятся.
Педагогический прием: Сравнение вывода to_tsvector('russian', 'Базами данных') и демонстрация лексемы 'баз':1. Объяснение, почему коммерческие поисковые интерфейсы строятся на FTS и инвертированных индексах.