157 lines
6.9 KiB
SQL
157 lines
6.9 KiB
SQL
--Задача 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 и тип сканирования.
|
||
--Index Scan, 0,06 мс после создания индекса.
|
||
|
||
Изменился ли тип сканирования?
|
||
-- да, изменился.
|
||
|
||
Стал ли запрос быстрее? На сколько?
|
||
--Да, в 21 раза
|
||
|
||
Почему индекс помог?
|
||
--Потому что не пришлось искать по всей таблице.
|
||
|
||
----------
|
||
|
||
--Задача 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(LOWER(email))
|
||
----------
|
||
|
||
--Задача 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 мс.
|
||
|
||
|
||
|