Files
homework/dmedvedev/2.1.theory_bd_indexes.sql
T
2026-07-09 23:38:46 +05:00

203 lines
13 KiB
SQL
Raw 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: По каким полям делать индексы
Возьми таблицы из пет проекта “Онлайн магазин”.
**Ответь:**
1. По каким полям, как тебе кажется, реальный продукт‑менеджер или аналитик будет чаще всего:
- искать (`WHERE`),
по странам пользователя, по категориям техники, стомиость, возраст пользователей, статус заказа, активность пользователей.
- сортировать (`ORDER BY`),
количество заказов, стоимость, возраст пользователей, дата заказа.
- группировать (`GROUP BY`),
по пользователям, по возрасту пользователей, по дате заказа (когорты), по статусу заказа, по категориям.
- соединять (`JOIN`)?
по u.id, o.user_id, p.id, oi.order_id, oi.product_id
2. Для каждого поля, которое ты назвал, укажи: «индекс нужен / индекс не нужен» и коротко объясни почему (часто фильтруем, редко фильтруем, мало разных значений и т.п.).
по странам пользователя ДА
по категориям техники ДА
стомиость ДА
возраст пользователей НЕТ
статус заказа ДА
активность пользователей ДА
дата заказа ДА
по пользователям НЕТ
по u.id ДА
o.user_id ДА
p.id ДА
oi.order_id ДА
oi.product_id ДА
- Задание 2. Свяжи запрос и индекс
**Придумай и напиши по одному SQL‑запросу для ситуаций:**
1. Найти пользователя по `email`.
SELECT
name,
email
FROM users
WHERE email = '';
Здесь лучше всего подойдет индекс по email. Ускорит WHERE.
2. Показать всех активных пользователей (`is_active = true`), зарегистрированных за последний год (`created_at`).
SELECT
name ,
created_at
FROM users
WHERE is_active = TRUE AND created_at > now() - interval '1 year';
Здесь лучше всего подойдет индекс по is_active, created_at. Ускорит WHERE.
3. Показать все товары категории `'electronics'`, отсортированные по `price` от низкой к высокой.
SELECT
name ,
price
FROM products
WHERE category = 'electronics'
ORDER BY price ASC;
Здесь лучше всего подойдет индекс по category, price. Ускорит WHERE и ORDER BY.
4. Показать все заказы конкретного пользователя за последние 30 дней по `user_id` и `order_date`.
SELECT
id,
o.id AS order_id,
order_date
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE order_date > now() - interval '30 days' AND u.id = ;
Здесь лучше всего подойдет индекс по order_date, o.user_id, u.id. Ускорит JOIN и WHERE.
5. Для каждого заказа показать товары в нём (используя `order_items`).
SELECT
o.id AS order_id,
p.name AS product_name
FROM orders o
JOIN order_items oi ON o.id = oi.order_id
JOIN products p ON p.id = oi.product_id;
Здесь лучше всего подойдут индексы по o.id, oi.order_id, p.id, oi.product_id. Ускорит JOIN.
**После этого:**
1. Для **каждого** запроса предложи **один индекс**, который поможет его ускорить.
2. Объясни словами: по каким полям индекс, в каком порядке (если их несколько) и какие части запроса он ускорит (`WHERE`, `JOIN`, `ORDER BY`).
***(Важно: сейчас не писать `CREATE INDEX` — только понять, какие индексы логичны.)***
- Задание 3. Порядок столбцов в индексе
Смотри на таблицу `orders`.
**Запросы:**
1. Все заказы пользователя за период:
WHERE user_id = ? AND order_date BETWEEN ? AND ?
2. Все заказы за период (без фильтра по пользователю):
WHERE order_date BETWEEN ? AND ?
3. Все заказы пользователя вообще:
WHERE user_id = ?
**Вопросы:**
1. Какой **один** составной индекс по полям `user_id` и `order_date` ты бы сделал (в каком порядке)?
CREATE INDEX idx_user_od ON orders(order_date, user_id)
2. Для каких из трёх запросов этот индекс будет работать особенно хорошо, а для каких — хуже? Объясни.
Для первого особенно хорошо, потому что будет по двух индексам.
Для остальных хуже потому что они фильтруют по одному индексу.
3. Сравни варианты:
- один индекс `(user_id, order_date)`
плюс: работает быстрее если сортируем по обоим столбцам
минус: не работает вообще если сортировать по order_date
- два индекса: `(user_id)` и `(order_date)`
плюс: гибкость
минус: требует больше места, иногда делает lookup
Напиши, в чём плюс и минус каждого подхода.
- Задание 4. Лишние индексы в наших таблицах
**Для каждой таблицы:**
1. users(...)
2. products(...)
3. orders(...)
4. order_items(...)
СКОРЕЕ НУЖЕН
u.id - связь по джойну и GROUP BY
u.age - можно применить в WHERE и ORDER BY
u.country - можно применить в WHERE и GROUP BY
u.is_active - можно применить в WHERE и GROUP BY
p.id - связь по джойну и GROUP BY
p.category - можно применить в WHERE и GROUP BY
p.price - можно применить в WHERE и ORDER BY
p.in_stock - можно применить в WHERE и GROUP BY
o.id - связь по джойну
o.user_id - связь по джойну и GROUP BY
o.status - можно применить в WHERE и GROUP BY
oi.order_id - связь по джойну и GROUP BY
oi.product_id - связь по джойну и GROUP BY
oi.price_at_purchase - можно применить в WHERE и ORDER BY
o.order_date - можно применить в WHERE и ORDER BY и GROUP BY
u.created_at - можно применить в WHERE и ORDER BY и GROUP BY
НА САМОМ ДЕЛЕ ИНДЕКСОВ ОЧЕНЬ МНОГО И ЛУЧШЕ КОНЕЧНО ИХ СОКРАТИТЬ, ЧТОБЫ БД МОГЛА БЫСТРЕЕ ВЫДАВАТЬ РЕЗУЛЬТАТ, ПОЭТОМУ ВЫБОР ДОБАВЛЕНИЯ ИЛИ УДАЛЕНИЯ ИНДЕКСА БУДЕТ ЗАВИСЕТЬ ОТ ПРОИЗВОДСТВЕННЫХ ЗАДАЧ.
СКОРЕЕ НЕ НУЖЕН
oi.quantity - не имеет смысла
p.name - не имеет смысла
u.email - все различны
u.name - не имеет смысла
Почему слишком много индексов замедляет INSERT, UPDATE и DELETE?
Индексы это средства для быстрого чтения данных, в этом они помогают. Но когда нам необзодимо добавить данные в таблицу, обновить или удалить, то в таком случае, БД должна будет и обратиться к индексам и их изменить тоже, поэтому слишком большое количество индексов в системе, которая предназначена для постоянного добавления/обновления данных, является негативным фактором.
**Сделай две группы столбцов:**
- «Скорее нужен индекс»
- «Скорее не нужен индекс»
И для **каждого** столбца, который ты туда попал, коротко напиши причину.
**В конце ответь текстом:** почему слишком много индексов замедляет INSERT, UPDATE и DELETE?
- Задание 5. Что должно быть уникальным
1. В таблице `users` выбери поля, которые должны быть уникальными в реальном проекте (например, `email`).
id, email
2. В таблице `products` выбери поле, которое в реальном магазине часто делают уникальным (например, какой‑то артикул — можешь придумать колонку `sku`, даже если её нет).
Например, это может быть поле name (например, айфон 15 про 128 гб серый) или как ты сказал артикул (sku)
3. Для каждого выбранного поля напиши:
- что будет, если уникальности не будет (какие реальные проблемы могут возникнуть);
В таком случае будет коллизия, задвоение или ошибка, например, человек покупает товар с определенным артикулом, в БД попадают данные о покупке товара с этим артикулом и случайно в заказ попадет два товара с одинаковым артиклом.
- почему вместо обычного индекса логичен **уникальный** индекс.
Чтобы случайно нельзя было добавить другой товар с таким же индексом. Разные индексы будут создавать уникальность для уникального товара.
- Задание 6. Где индексы помогут, а где нет
Для каждого запроса оцени: «индекс нужен / не нужен», и если нужен — по каким полям:
1. SELECT * FROM users WHERE id = 100; нужен по полю id
2. SELECT * FROM users WHERE email = 'user@example.com'; не нужен
3. SELECT * FROM products WHERE price BETWEEN 100 AND 500; нужен по price
4. SELECT * FROM products WHERE name LIKE '%phone%'; нужен по name
5. SELECT * FROM orders WHERE status = 'DELIVERED'; нужен по status
6. SELECT * FROM order_items WHERE order_id = 123; нужен по order_id
**Ответ — текстом:**
В чём выгода индекса и где он не поможет
Индекс помогает искать данные быстрее (индекс это как содержание в книге). Индекс не поможет в тех столбцах, где все данные в столбце различаются, например email.