- Задание 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(user_id, order_date) 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'; нужен по полю email 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 **Ответ — текстом:** В чём выгода индекса и где он не поможет Индекс помогает искать данные быстрее (индекс это как содержание в книге) за счет плана в виде дерева. Индекс не поможет в тех столбцах, где уникальность данных мала, а также где есть сортировка по знакам >, < или поиск по части строки = "%abc".