практика 'EXPLAIN и EXPLAIN ANALYZE'
This commit is contained in:
+203
@@ -0,0 +1,203 @@
|
|||||||
|
-- Задание 1
|
||||||
|
EXPLAIN
|
||||||
|
SELECT
|
||||||
|
name, email
|
||||||
|
FROM
|
||||||
|
users
|
||||||
|
WHERE
|
||||||
|
id = 1;
|
||||||
|
-- Использует index scan
|
||||||
|
-- Index Cond: (id = 1) - это значит что условие id = 1, и оно выполняется по индексу, и что id - индекс
|
||||||
|
-- База использует индекс, потому что у нас по полю id создан индекс, и база выбирает наиболее быстрый пусть ввыполнения запроса - через индекс
|
||||||
|
|
||||||
|
|
||||||
|
-- Задание 2
|
||||||
|
-- Запрос А
|
||||||
|
EXPLAIN
|
||||||
|
SELECT * FROM users WHERE id = 2;
|
||||||
|
|
||||||
|
-- Запрос Б
|
||||||
|
EXPLAIN
|
||||||
|
SELECT * FROM users WHERE age > 25;
|
||||||
|
-- В первом запрос index scan, потому что у нас уловие по индексу - id, во втором запросы seq scan, потому что у поля age не индексов, и таблица сканируется медленее
|
||||||
|
|
||||||
|
|
||||||
|
-- Задание 3
|
||||||
|
EXPLAIN ANALYZE
|
||||||
|
SELECT
|
||||||
|
name, price
|
||||||
|
FROM
|
||||||
|
products
|
||||||
|
WHERE
|
||||||
|
category = 'Электроника';
|
||||||
|
-- Execution Time: 0.020 ms
|
||||||
|
-- Тип сканирования: Seq Scan
|
||||||
|
-- Ожидалось вернуть 1, а вернул 3
|
||||||
|
|
||||||
|
|
||||||
|
-- Задание 4
|
||||||
|
EXPLAIN ANALYZE
|
||||||
|
SELECT * FROM users WHERE country = 'RU';
|
||||||
|
-- Без индекса - Execution Time: 6.769 ms
|
||||||
|
CREATE INDEX idx_country ON users(country);
|
||||||
|
-- С индексом - Execution Time: 2.076 ms
|
||||||
|
-- Сначала идет Bitmap Heap Scan on users - как я понял на этом этапе 'создается' таблица где country = 'RU', а потом Bitmap INdex Scan on idx_country - тут уже мы читам информацию из таблицы где все country = 'RU'.
|
||||||
|
-- Запрос стал быстрее примерно в три раза
|
||||||
|
-- Индекс помог, потому что база искала не среди всех данных, а среди 'проиндексированных'
|
||||||
|
|
||||||
|
|
||||||
|
-- Задание 5
|
||||||
|
EXPLAIN ANALYZE
|
||||||
|
SELECT
|
||||||
|
u.name, o.order_date, o.status
|
||||||
|
FROM
|
||||||
|
users u
|
||||||
|
JOIN
|
||||||
|
orders o ON u.id = o.user_id
|
||||||
|
WHERE
|
||||||
|
u.country = 'RU';
|
||||||
|
-- База исполщовала Nested Loop
|
||||||
|
-- Чтение началось с orders
|
||||||
|
-- Execution Time: 0.075 ms
|
||||||
|
|
||||||
|
|
||||||
|
-- Задание 6
|
||||||
|
CREATE INDEX idx_email ON users(email);
|
||||||
|
EXPLAIN ANALYZE
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
users
|
||||||
|
WHERE
|
||||||
|
lower(email) = 'user_28@example.com';
|
||||||
|
-- База не использует индекс пока в where есть функция lower
|
||||||
|
-- Потому что в условии функция, а с ними индексы не в ладах как я понял
|
||||||
|
-- Чтобы индекс заработал, надо убрать функцию lower, и сравнивать email как есть
|
||||||
|
-- Если убрать lower, то Execution Time намного быстрее, прям очень намного быстрее
|
||||||
|
|
||||||
|
|
||||||
|
-- Задание 7
|
||||||
|
CREATE INDEX idx_age ON users(age);
|
||||||
|
-- Запрос А
|
||||||
|
EXPLAIN ANALYZE
|
||||||
|
SELECT * FROM users WHERE age + 5 > 30;
|
||||||
|
|
||||||
|
-- Запрос Б
|
||||||
|
EXPLAIN ANALYZE
|
||||||
|
SELECT * FROM users WHERE age > 25;
|
||||||
|
-- Быстрее работает запрос Б, но че то он тоже не хочет индекс использовать, хотя я его создал
|
||||||
|
-- Первый запрос не может использовать индекс, потому что там в условии математическое вычисление, а почему второй запрос не использует индек - я хз
|
||||||
|
-- Чтобы исправить запрос надо убрать сложение, и просто написать age > 25, как в запросе Б
|
||||||
|
|
||||||
|
|
||||||
|
-- Задание 8
|
||||||
|
CREATE INDEX idx_created_at ON users(created_at);
|
||||||
|
EXPLAIN ANALYZE
|
||||||
|
SELECT u.name, COUNT(o.id) AS orders_count
|
||||||
|
FROM users u
|
||||||
|
LEFT JOIN orders o ON u.id = o.user_id
|
||||||
|
WHERE EXTRACT(YEAR FROM u.created_at) = 2026
|
||||||
|
GROUP BY u.name;
|
||||||
|
-- Функция EXTRACT - это плохая идея, потому что это функция которой быть в where по возможности не должно
|
||||||
|
-- WHERE i.crated_at BETWEEN '2026-01-01' AND '2027-01-01'
|
||||||
|
-- Индекс не используется в текущеа виде
|
||||||
|
|
||||||
|
|
||||||
|
-- Задание 9
|
||||||
|
-- Запрос А
|
||||||
|
EXPLAIN ANALYZE
|
||||||
|
SELECT * FROM products WHERE price > 50000;
|
||||||
|
|
||||||
|
-- Запрос Б
|
||||||
|
EXPLAIN ANALYZE
|
||||||
|
SELECT name, price FROM products WHERE price > 50000;
|
||||||
|
-- Если будет много данных в таблице, то быстрее будет работать второй запрос
|
||||||
|
-- Второй эффективнее тк в селекте указаны определнные поля, а не все(*)
|
||||||
|
-- Разница будет особо замета при больших объемах данных
|
||||||
|
|
||||||
|
|
||||||
|
-- Задание 10
|
||||||
|
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' AND p.category = 'Электроника';
|
||||||
|
-- Порядок чтения таблиц: order_items -> products -> orders -> users
|
||||||
|
-- Количество строк: order_items - 12, products - 3, orders - 1, users - 0
|
||||||
|
-- Если у country и category будут индексы, то запрос ьудет выполняться побыстре, потому что будет Index Scan, а не Seq Scan
|
||||||
|
|
||||||
|
|
||||||
|
-- Задание 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;
|
||||||
|
-- Execution Time: 0.219 ms
|
||||||
|
|
||||||
|
-- После
|
||||||
|
EXPLAIN ANALYZE
|
||||||
|
SELECT *
|
||||||
|
FROM users u
|
||||||
|
JOIN orders o ON u.id = o.user_id
|
||||||
|
WHERE u.name = 'иван' AND
|
||||||
|
o.order_date BETWEEN '2024-01-01' AND '2024-02-01' AND
|
||||||
|
O.order_date BETWEEN '2026-01-01' AND '2026-02-01' AND
|
||||||
|
u.age > 25;
|
||||||
|
-- Execution Time: 0.032 ms
|
||||||
|
-- Мой вариант лучще, потому что у меня нет функций и вычисление мешаюзих использовать индексы в условии, и оптимизатор может успешно использовать индексы
|
||||||
|
|
||||||
|
|
||||||
|
-- Задание 12
|
||||||
|
-- Запрос 1
|
||||||
|
EXPLAIN ANALYZE
|
||||||
|
SELECT
|
||||||
|
o.user_id,
|
||||||
|
o.id AS order_id
|
||||||
|
FROM
|
||||||
|
users u
|
||||||
|
JOIN
|
||||||
|
orders o ON u.id = o.user_id AND u.country = 'RU';
|
||||||
|
|
||||||
|
-- Запрос 2
|
||||||
|
EXPLAIN ANALYZE
|
||||||
|
SELECT
|
||||||
|
o.user_id,
|
||||||
|
o.id AS order_id
|
||||||
|
FROM
|
||||||
|
orders o
|
||||||
|
WHERE EXISTS (
|
||||||
|
SELECT
|
||||||
|
1
|
||||||
|
FROM
|
||||||
|
users u
|
||||||
|
WHERE
|
||||||
|
o.user_id = u.id AND
|
||||||
|
u.country = 'RU'
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Запрос 3
|
||||||
|
EXPLAIN ANALYZE
|
||||||
|
SELECT
|
||||||
|
o.user_id,
|
||||||
|
o.id AS order_id
|
||||||
|
FROM
|
||||||
|
orders o
|
||||||
|
WHERE o.user_id IN (
|
||||||
|
SELECT
|
||||||
|
u.id
|
||||||
|
FROM
|
||||||
|
users u
|
||||||
|
WHERE
|
||||||
|
u.country = 'RU'
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Запрос 1: Execution Time: 0.055 ms
|
||||||
|
-- Запрос 2: Execution Time: 0.051 ms
|
||||||
|
-- Запрос 3: Execution Time: 0.073 ms
|
||||||
|
-- Они все дют примерно одинаковый разультат, потому что мало данных в таблице. А планы выполнения у них у всех одинаковые, вот прям 1 в 1. Ну по логие 3 запрос самый медленный, а первые два шустрые
|
||||||
Reference in New Issue
Block a user