homework, pet project DE Dmitry_Medvedev #1

Open
dmitry_medvedev wants to merge 264 commits from md_branch into main
Showing only changes of commit 6f96ed5510 - Show all commits
+192
View File
@@ -0,0 +1,192 @@
- **Задача 1** — Когда какой метод?
✅ Заполни таблицу:
| **Ситуация** | **Какой JOIN выберет база?** | **Почему?** |
| --- | --- | --- |
| 10 пользователей, 1 млн заказов, есть индекс на orders.user_id | Nested Loop | Потому что есть индекс по одному полю и одна таблица мееьше другой сильно |
| 100 000 пользователей, 100 000 заказов, нет индексов | Hash Join | Нет ни индексов, ни сортировки |
| Обе таблицы отсортированы по ключу, есть индексы | Merge Join | Потому что есть и индексы и сортировка |
| Маленькая таблица (5 строк) соединяется с большой (1 млн строк), нет индекса | Hash Join | Потому что нет индекса |
- **Задача 2** — Размер таблиц имеет значение
✅ Создай тестовые данные:
-- Маленькая таблица (10 строк)
CREATE TABLE small_users AS
SELECT generate_series(1, 10) AS id, 'User ' || generate_series(1, 10) AS name;
-- Большая таблица (100 000 строк)
CREATE TABLE big_orders AS
SELECT
generate_series(1, 100000) AS id,
(random() * 9 + 1)::int AS user_id,
CURRENT_DATE - (random() * 365)::int AS order_date;
✅ Теперь выполни:
-- Вариант 1: Без индекса
EXPLAIN ANALYZE
SELECT u.name, COUNT(o.id)
FROM small_users u
JOIN big_orders o ON u.id = o.user_id
GROUP BY u.name;
-- Вариант 2: С индексом
CREATE INDEX idx_big_orders_user_id ON big_orders(user_id);
EXPLAIN ANALYZE
SELECT u.name, COUNT(o.id)
FROM small_users u
JOIN big_orders o ON u.id = o.user_id
GROUP BY u.name;
**❓ Вопросы:**
1. Какой метод `JOIN` используется в каждом случае?
В обоих случаях у меня показало Merge Join, просто там где индекс - там Scan Index.
2. Почему с индексом база может выбрать `Nested Loop`?
Потому что будет маленькая таблица, иногда проще заджойнить большую и маленькую Nested Loop.
3. Насколько быстрее стало с индексом?
В 2,5 раза.
- **Задача 3** — Влияние сортировки
✅ Выполни три варианта:
-- Вариант 1: Без ORDER BY
EXPLAIN ANALYZE
SELECT u.name, o.order_date
FROM users u
JOIN orders o ON u.id = o.user_id;
-- Вариант 2: С ORDER BY по ключу соединения
EXPLAIN ANALYZE
SELECT u.name, o.order_date
FROM users u
JOIN orders o ON u.id = o.user_id
ORDER BY u.id, o.user_id;
-- Вариант 3: С ORDER BY по другому полю
EXPLAIN ANALYZE
SELECT u.name, o.order_date
FROM users u
JOIN orders o ON u.id = o.user_id
ORDER BY o.order_date;
**❓Вопросы:**
1. Изменился ли тип `JOIN` во втором варианте?
В первом Hash, во втором - Merge.
2. Появился ли `Merge Join`?
Да.
3. Почему `ORDER BY` может повлиять на выбор `JOIN`?
Потому что появляется метод при соединении (при условии наличия order by), упрощающий join.
- **Задача 4** — Найди узкое место
✅ Дан медленный запрос:
SELECT
u.name,
p.name AS product_name,
oi.quantity,
o.order_date
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 = 'Россия';
**✅ Задание:**
1. Выполни с `EXPLAIN ANALYZE`
2. Посмотри, какие типы `JOIN` используются
Nested Loop and Hash Join.
3. Есть ли `Seq Scan`? Если да — где?
Да, в трех местах. При чтении таблицы users, orders и products.
4. Предложи, какие индексы нужно создать
Можно создать 3 индекса
5. Создай индексы и проверь, изменились ли типы `JOIN`
Изменились, но не сильно, в основном все Hash, один внешний Nested
- **Задача 5** — Многоступенчатый JOIN
EXPLAIN ANALYZE
SELECT
u.name,
COUNT(DISTINCT o.id) AS orders_count,
COUNT(DISTINCT oi.product_id) AS products_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
LEFT JOIN order_items oi ON o.id = oi.order_id
WHERE u.country = 'Россия'
GROUP BY u.name;
**✅ Задание:**
1. Посмотри на план выполнения
2. Какие методы `JOIN` используются на каждом уровне?
Hash right join 2 раза
3. Почему для первого `JOIN` один метод, а для второго — другой?
У меня оба одинаковые, вероятнее всего из-за неверных индексов или чего-то другого.
4. Сколько строк проходит через каждый `JOIN`?
По одной
- **Задача 6** — `LEFT JOIN` vs `INNER JOIN`
✅ Сравни два запроса:
-- Вариант A: INNER JOIN
EXPLAIN ANALYZE
SELECT u.name, o.order_date
FROM users u
INNER JOIN orders o ON u.id = o.user_id;
-- Вариант B: LEFT JOIN
EXPLAIN ANALYZE
SELECT u.name, o.order_date
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;
**❓ Вопросы:**
1. Одинаковый ли тип физического JOIN используется?
Hash and Hash Right
2. Есть ли разница в Execution Time?
Не сильно , скачет то в одну, то в другую сторону
3. Почему LEFT JOIN может быть медленнее?
- **Задача 7** — Порядок таблиц в JOIN
✅ Сравни:
-- Вариант 1: users JOIN orders
EXPLAIN ANALYZE
SELECT u.name, o.order_date
FROM users u
JOIN orders o ON u.id = o.user_id;
-- Вариант 2: orders JOIN users
EXPLAIN ANALYZE
SELECT u.name, o.order_date
FROM orders o
JOIN users u ON o.user_id = u.id;
**❓ Вопросы:**
1. Изменился ли тип `JOIN`?
нет
2. Изменился ли порядок чтения таблиц в плане?
нет
3. Одинаковое ли `Execution Time`?
Да
4. Почему оптимизатор может выбрать разный порядок?
потому чтт ему будет так проще соединять таблицы и читать данные