--Задача 1 — Читаем план EXPLAIN SELECT name, email FROM users WHERE id = 1; Какой тип сканирования использует база? --SeqScan - сканирование всей таблицы Что означает строка `Index Cond: (id = 1)`? -- Строка означает фильтрацию столбца по индексу, который есть в столбце id. Почему база использует индекс, а не читает всю таблицу? --В моем случае БД читает всю таблицу, но обычно если индексы расставлены верно и таблица больших размеров, то БД лучше использовать индексы для повышенной производительности. ---------- --Задача 2 — Seq Scan vs Index Scan Почему в первом запросе используется Index Scan, а во втором может быть Seq Scan (если нет индекса на age)? --Потому что Seq Scan сканирует таблицу полностью и ищет значения, а вот Index Scan нет необходимости сканировать всю таблицу, он отсекает по индексу. ---------- --Задача 3 — Замеряем время 1. Запиши **Execution Time** --0.023 мс 2. Определи тип сканирования (Seq Scan или Index Scan) --Seq Scan 3. Сколько строк вернул запрос? --вернул 3 строки ---------- --Задача 4 — До и после индекса Запиши Execution Time и тип сканирования. --Seq Scan, 0.059 мс, после создания индекса запрос составил 0.026мс Изменился ли тип сканирования? -- Нет, не изменился, не могу понять почему. Стал ли запрос быстрее? На сколько? --Да, в 2 раза Почему индекс помог? --Потому что не пришлось искать по всей таблице. ---------- --Задача 5 — Анализируем JOIN Какой тип JOIN использует база (Hash Join, Nested Loop, Merge Join)? --Hash С какой таблицы база начала чтение? -- с users Сколько времени занял весь запрос? --execution time 0.032ms ---------- --Задача 6 — Почему медленно? 1. Выполни запрос и посмотри на план --посмотрел 2. Использует ли база индекс? --нет, используется seq scan 3. Почему НЕТ? (даже если индекс на email есть) --Думаю, потому что также используется функция LOWER внутри WHERE 4. Как исправить запрос, чтобы индекс заработал? CREATE INDEX idx_email ON users(email); --я добавил индекс, но все равно EXPLAIN ANALYZE показывается Seq Scan. В чем проблема? ---------- --Задача 7 — Функции убивают индексы Какой запрос работает быстрее? --тот где нет дополнительной математики в условии Почему первый запрос НЕ может использовать индекс на `age`? --потому что появилась функция Как правильно переписать запрос А? -- убрать функцию из условия: EXPLAIN ANALYZE SELECT * FROM users WHERE age > 35; ---------- --Задача 8 — Диагностика медленного запроса 1. Почему функция `EXTRACT()` — плохая идея? --потому что она мешает оптимизатору применить индекс. 2. Как переписать условие WHERE без функции? --добавлением граничных условий что-то по типу created_at>='2026-01-01' AND created_at<'2027-01-01' 3. Будет ли использоваться индекс на `created_at` в текущем виде? --нет, по описанным выше условиям ---------- --Задача 9 — SELECT * против конкретных колонок Какой запрос работает быстрее? -- запрос Б, там где выбираются не все столбцы Почему второй может быть эффективнее (даже если тип сканирования одинаковый)? --потому что объем обработанной информации меньше В каких ситуациях разница будет особенно заметна? --когда вся таблица изначально состоит из множества столбцов (более 10), а вт втором запросе мы берем только пару И когда количество строк очень большой. ---------- --Задача 10 — Оптимизируем JOIN с условием 1. Выполни запрос и посмотри на план посмотрел 2. В каком порядке база читает таблицы? БД читает таблицы в порядке, который является наименее затратным. Сначала идет отфильтровывание по условию,далее создается хэш таблица и хэш соединение, соединение по индексу. 3. Сколько строк проходит через каждый JOIN? У меня здесь только 1 hash join - там 5 строк. Но сразу скажу, что одно из условий я удалил, так что у меня осталось только одно условие с category. 4. Можно ли оптимизировать? (Подсказка: подумай про индексы на `country` и `category`) Я добавил индекс на category, поменялось количество hash join, стало 2. Но сканирование не изменилось на индекс. Видимо, это связано с тем, что оптимизатору проще проходить по всей таблице, чем искать по индексу ввиду того, что таблица сама по себе не большая. ---------- --Задача 11 — Найди и исправь Основной запрос EXPLAIN ANALYZE SELECT * FROM users u LEFT JOIN orders o ON u.id = o.user_id WHERE LOWER(u.name) LIKE '%иван%' AND EXTRACT(MONTH FROM o.order_date) = 1 AND u.age + 10 > 35; Оптимизированный EXPLAIN ANALYZE SELECT u.name, o.order_date, u.age FROM users u LEFT JOIN orders o ON u.id = o.user_id WHERE u.name LIKE '%иван%' AND o.order_date >= '2024-01-01' AND o.order_date < '2024-02-01' AND u.age > 25; По моим данным ожидаемое кол-во строк = 0, поэтому и запросы отрабатываются быстро = 0.03 мс.