практика 'Оптимизатор запросов'
This commit is contained in:
@@ -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;
|
||||||
|
-- Ну чето все равно не видна разница во времени выполнения, но по логике должен быть быстрее второй запрос
|
||||||
Reference in New Issue
Block a user