Files
homework/dmedvedev/10.6.Logic_and_Physics_joins.sql
2026-07-04 13:47:18 +05:00

193 lines
7.5 KiB
SQL
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
- **Задача 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. Почему оптимизатор может выбрать разный порядок?
потому чтт ему будет так проще соединять таблицы и читать данные