homework, pet project DE Dmitry_Medvedev #1
@@ -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. Почему оптимизатор может выбрать разный порядок?
|
||||
потому чтт ему будет так проще соединять таблицы и читать данные
|
||||
|
||||
Reference in New Issue
Block a user