практика 'Оптимизатор запросов'

This commit is contained in:
mnoskov
2026-03-13 16:07:02 +03:00
parent f4eaf9d640
commit 508e077da3
@@ -0,0 +1,165 @@
-- Задание 1
-- Вариант А
EXPLAIN ANALYZE
SELECT name, age
FROM mnoskov.users
WHERE country = 'RU' AND age > 25;
-- Вариант Б
EXPLAIN ANALYZE
SELECT name, age
FROM mnoskov.users
WHERE age > 25 AND country = 'RU';
-- Выводят они один и тот же результат, потому что условия у них одинаковые
-- По скорости выполнения судя по планировщику тоже одинаковоы
-- Задание 2
-- Вариант 1
EXPLAIN ANALYZE
SELECT
u.name,
u.email,
o.order_date::date,
o.status
FROM
mnoskov.users u
JOIN
mnoskov.orders o ON u.id = o.user_id
WHERE o.status = 'refunded';
-- Вариант 2
EXPLAIN ANALYZE
SELECT
u.name,
u.email,
o.order_date::date,
o.status
FROM
mnoskov.orders o
JOIN
mnoskov.users u ON o.user_id = u.id
WHERE o.status = 'refunded';
-- Между первой и второй таблицей результаты одинаковые. Если в запросе нет никаких условий связанных с таблицами, то первой оптимизатор смотреть users, но если если условие по orders.status, то сначала он сканирует orders
-- Задание 3
EXPLAIN ANALYZE
SELECT name, email
FROM mnoskov.users
WHERE country = 'RU';
-- Тип сканирования: Seq Scan
-- Количество прочитанных строк: 1
-- Время выполнения примерно: 0.023 ms(+-5)
-- Задание 4
-- Запрос А
EXPLAIN ANALYZE
SELECT *
FROM mnoskov.users
WHERE country = 'RU';
-- Запрос Б
EXPLAIN ANALYZE
SELECT name, email
FROM mnoskov.users
WHERE country = 'RU';
-- Поскольку данных в таблице мало у меня время выполнения одинаковое, но могу предположить, что второй выполнился быстрее, тк у него в селекте два поля, а не вся таблица
-- Задание 5
EXPLAIN ANALYZE
SELECT
u.name, o.id, o.order_date
FROM
mnoskov.users u
JOIN
mnoskov.orders o ON u.id = o.user_id
WHERE
u.country = 'RU';
-- Читать начала с users, тк мы в where пишем условие для users, и быстрее сначала отсеять ненужных юзеров
-- Задание 6
SELECT u.name, COUNT(o.id) AS orders_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.country = 'Россия'
AND LOWER(u.name) LIKE '%алекс%'
GROUP BY u.name;
-- Его замедляет LOWER(не надо использовать функции), и думаю что LIKE(лучше использовать просто =), и ещэ group by по имени - это дольше чем по первичному ключу(надо группировать по ПК)
-- Задание 7
EXPLAIN ANALYZE
SELECT u.name, p.name AS product_name, oi.quantity
FROM users u
JOIN orders o ON u.id = o.user_id
JOIN order_items oi ON o.id = oi.order_id
JOIN products p ON oi.product_id = p.id
WHERE u.country = 'RU';
-- users -> orders -> order_items -> products - читает в таком порядке, потому что в where условие по users
-- Если убрать where, то будет - order_items -> users -> orders -> products
-- Как ускорить не знаю, может индексов добавть, но это пока не проходил
-- Задание 8
-- Вариант А
EXPLAIN ANALYZE
SELECT name, price
FROM mnoskov.products
WHERE category = 'Электроника'
AND price > 50000;
-- Вариант Б
EXPLAIN ANALYZE
SELECT *
FROM mnoskov.products
WHERE category = 'Электроника'
AND price > 50000;
-- Данных в таблицах мало, врем выполнения не оценить, но смотря просто со стороны понятно что выриант А будет быстрее, потому что у него пару колонок в селекте, а не вся таблица как в Б
-- Задание 9
-- Вариант коллег
SELECT *
FROM users
WHERE EXTRACT(YEAR FROM created_at) = 2026
AND LOWER(country) = 'россия'
AND age + 10 > 35;
-- Мой вариант
SELECT
id, name, age, is_active
FROM
mnoskov.users
WHERE
created_at BETWEEN '2026-01-01' AND '2027-01-02' AND
country = 'RU' AND
age > 45;
-- Мой вариант лучше потому что:
-- нет функций и мат. вычислений в where, все приведено к самому легкочитаемому формату
-- нет звездочки в select, а только то, что нужно
-- Задание 10
INSERT INTO users (id, name, age, email, country, created_at)
SELECT
g AS id,
'user_' || g AS name,
27 AS age,
'user_' || g || '@example.com' AS email,
'RU' AS country,
'2026-02-03' AS created_at
FROM generate_series(20001, 50000) AS g; -- GPT сделал запрос мне
SELECT * FROM mnoskov.users WHERE age IS NOT NULL;
-- Запрос 1
EXPLAIN ANALYZE
SELECT * FROM users WHERE age > 25;
-- Запрос 2
EXPLAIN ANALYZE
SELECT name, email FROM users WHERE age > 25;
-- Ну чето все равно не видна разница во времени выполнения, но по логике должен быть быстрее второй запрос