From cfb837fcbf2adef4cc443613bb4bc88674addf86 Mon Sep 17 00:00:00 2001 From: Dmitry Medvedev Date: Sat, 11 Jul 2026 17:52:38 +0500 Subject: [PATCH] added theory bd b-tree and hash indexes --- dmedvedev/2.5.theory_bd_b_tree_hash_index.sql | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 dmedvedev/2.5.theory_bd_b_tree_hash_index.sql diff --git a/dmedvedev/2.5.theory_bd_b_tree_hash_index.sql b/dmedvedev/2.5.theory_bd_b_tree_hash_index.sql new file mode 100644 index 0000000..aa261e5 --- /dev/null +++ b/dmedvedev/2.5.theory_bd_b_tree_hash_index.sql @@ -0,0 +1,104 @@ +- Задание 1: + + **Дана таблица:** + + users(id PK, email, age, created_at) + + + **И индекс:** + + CREATE INDEX idx_users_email ON users(email); + + + **Ответь для каждого варианта:** + + - будет ли использоваться этот индекс; + - если нет — что нужно изменить (индекс или запрос). + + **Варианты:** + + 1. SELECT * FROM users WHERE email = 'test@example.com'; // будет, менять ничего не нужно + 2. SELECT * FROM users WHERE LOWER(email) = 'test@example.com'; // не будет, нужно изменить запрос, а именно убрать функцию LOWER + 3. SELECT * FROM users WHERE email LIKE 'alex%'; // будет, все норм + 4. SELECT * FROM users WHERE email LIKE '%@gmail.com'; // не будет, так как ищем оканчание строки. не знаю что тут можно поменять, как-будто ничего + 5. SELECT * FROM users ORDER BY email LIMIT 10; // будет, все норм + 6. SELECT * FROM users WHERE age BETWEEN 20 AND 30; // будет, все норм, но только B-tree +- Задание 2: + + **Дана таблица заказов:** + + orders( + id PK, + user_id, + status, + created_at, + amount + ); + + **К каждому запросу нужно сказать, что индекс не нужен/бесполезен):** + + 1. История заказов пользователя за период: + + SELECT * + FROM orders + WHERE user_id = 123 + AND created_at BETWEEN '2025-01-01' AND '2025-02-01' + ORDER BY created_at; + + + 2. Ежедневная агрегация по статусу: + + SELECT date_trunc('day', created_at) AS day, + status, + count(*) + FROM orders + GROUP BY day, status; + + + 3. Проверка наличия хотя бы одного «висящего» заказа: + + SELECT 1 + FROM orders + WHERE status = 'pending' + LIMIT 1; + + **Напиши `CREATE INDEX ...` и объясни, почему такой порядок колонок** +1. CREATE INDEX idx_orders_user_id_created_at ON orders (user_id, created_at) + ТАК ЭФФЕКТИВНЕЕ ПОТОМУ ЧТО СНАЧАЛА НАХОДИТСЯ ПОЛЬЗОВАТЕЛЕЙ, А ПОТОМ ДИАПАЗОН ЕГО ДАТ. ИНАЧЕ ПРИШЛОСЬ БЫ СНАЧАЛА ФИЛЬТРОВАТЬ ДИАПАЗОН ДАТ, А ПОТОМ НЕ НУЖНЫХ ПОЛЬЗОВАТЕЛЕЙ. + +2. В ДАННОМ СЛУЧАЕ ИНДЕКС НЕ НУЖЕН ПОТОМУ ЧТО НЕТ УСЛОВИЯ В КОДЕ, ПОСТГРЕ ПРИДЕТСЯ В ЛЮБОМ СЛУЧАЕ СМОТРЕТЬ ВСЮ ТАБЛИЦУ. + +3. CREATE INDEX idx_status_peding ON orders (status) WHERE status = 'pending' + ЗДЕСЬ МОЖНО ИСПОЛЬЗОВАТЬ ИНДЕКС ТОЛЬКО ПО ОДНОМУ ПОЛЮ "pending" ЧТОБЫ НЕ ИНДЕКСИРОВАТЬ ВСЕ ЗНАЧЕНИЯ ПО ДАННОМУ СТОЛБЦУ status + + +- Задание 3: + + Та же таблица `orders` + + **Выбери тип индекса и объясни почему выбрал такой для вариантов:** + + 1. SELECT * FROM orders WHERE id = 100500; // hash , возможное соединение таблиц + 2. SELECT * FROM orders WHERE status = 'paid'; // спорен + 3. SELECT * FROM orders WHERE created_at BETWEEN ...; // только B-tree из-за диапазона + 4. SELECT * FROM orders WHERE user_id = 123; // hash, возможное соединение таблиц + + **Вопросы:** + + - Где hash имел бы смысл? + - Где обязательно B‑tree? + - Где индекс вообще спорен? +- Задание 4: + + **Исходные индексы:** + + CREATE INDEX idx_orders_user_created ON orders(user_id, created_at); + CREATE INDEX idx_orders_user ON orders(user_id); + + **Задача:** + + - объяснить, зачем нужен первый; + ЧТОБЫ ОДНОВРЕМЕННО ИСКАТЬ ПОЛЬЗОВАТЕЛЕЙ В СОВОКУПНОСТИ С ДАТОЙ СОЗДАНИЯ. И ТАКЖЕ СОРТИРОВАТЬ ПО ДАТЕ СОЗДАНИЯ ПОЛЬЗОВАТЛЕЙ . + + - нужен ли второй или его можно удалить; + ВТОРОЙ НЕ НУЖЕН, ПОТОУ ЧТО ПЕРВЫЙ МОЖЕТ РАБОТАТЬ ПО ЛЕВОМУ ПРЕФИКСУ. ВТОРОЙ ИНДЕКС ЛИШЬ ЗАНИМАЕТ ЛИШНЕЕ МЕСТО. \ No newline at end of file