added explain and poryadok sql

This commit is contained in:
Dmitry Medvedev
2026-06-30 13:54:42 +05:00
parent 03149fb22c
commit 3581c6c741
2 changed files with 398 additions and 0 deletions
+151
View File
@@ -0,0 +1,151 @@
--Задача 1 — Читаем план
Какой тип сканирования использует база?
--SeqScan - сканирование всей таблицы
Что означает строка `Index Cond: (id = 1)`?
-- У меня нет такой строки, есть "Filter: (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 мс.