/* Задание 1. Какой вид партиционирования выбрать 1) * range по полю order_date * запросы с between в год 1. where order_date between '2022-01-01' and '2023-01-01' 2. where extract('year' from order_date) = '2025' 3. where order_date < '2026-01-01' and order_date > '2025-01-01' 2) * тут два типа партиционирования подходят. range по created_at или list по country. * если выбирать list по country то плюс - это при фильтрах по стране будут отсекаться лишние партиции, а минус, что год/месяц регистрации не будет разделен по партициям. 3) * логично range по created_at - чтобы разделить по месяцам/годам, а hash по user_id - почему так, точно сказать не могу, но в теории сказано что hash используется когда нет диапазона или списка и это частый сценарий для логов * с range выиграют запросы с фильтрами по created_at, а с hash выигают запросы с фильтрами по user_id, а все что не указаны как поле для партиций, не почувствуют разницы.*/ /* Задание 2. Размер партиций 2) количество партициый за 10 лет по: * годам - 10, тут вообще все четко, и удалять не сложно, и поддержка проще, и запросы будут хорошо делаться * месяцам - 120, тут с удалением тарых данных труднее, поддержка тяжелая, но скорость запросов будет лучше, если фильтрация будет по месяцам * дням - примерно 3650, а это я чувствую пиздец, с удалением и поддержкой жопа, и со скоростью запросов тоже жопа - данные будут читаться из кучи партиций что не есть хорошо 3) Я думаю прям для очень большого магазина оптимальнее будет партиционирование по месяцам - тк очень много покупателей и большинство статистик будет по месяцам, по годам тоэе конечно, но думаю приоритетнее по месяцам*/ -- Задание 3. RANGE‑партиции по дате заказов DROP TABLE IF EXISTS orders_part; CREATE TABLE orders_part ( id bigint, user_id bigint, order_date timestamptz NOT NULL, status varchar(20), PRIMARY KEY (id, order_date), FOREIGN KEY (user_id) REFERENCES users_1(id) ) PARTITION BY RANGE (order_date); CREATE TABLE orders_2024 PARTITION OF orders_part FOR VALUES FROM ('2024_01-01') TO ('2025-01-01'); CREATE TABLE orders_2025 PARTITION OF orders_part FOR VALUES FROM ('2025_01-01') TO ('2026-01-01'); CREATE TABLE orders_2026 PARTITION OF orders_part FOR VALUES FROM ('2026_01-01') TO ('2027-01-01'); -- сделал insert который попросил сгенерировать нейронку EXPLAIN ANALYZE SELECT * FROM orders_part WHERE order_date BETWEEN '2025-01-01' AND '2025-12-31 23:59:59'; -- пришлось сделать так, тк дата 2026-01-01 тоже есть в таблице -- в этом запросе за год - читатется только одна партиция - orders_2025, НО если в условии все же написать AND '2026-01-01', то читаются две партиции orders_2025 и orders_2026 и время выполнения запроса намного больше тк выполняется full scan обеих таблиц EXPLAIN ANALYZE SELECT * FROM orders_part WHERE EXTRACT('year' FROM order_date) IN ('2024', '2025'); -- так читаются все три партиции, 2026 почему-то тоже захватывается, но по итогу после сканирование у таблицы orders_2026 - rows = 0 EXPLAIN ANALYZE SELECT * FROM orders_part; -- так просто сканируются все три партиции, но без фильтров, как было в предидущем варианте -- Задание 4. LIST‑партиции по стране пользователей DROP TABLE IF EXISTS users_part; CREATE TABLE users_part ( id int8 NOT NULL, "name" varchar(100) NOT NULL, age int2 NULL, email varchar(100) NULL, country bpchar(2) NULL, is_active bool NULL, created_at timestamptz NOT NULL, PRIMARY KEY (id, country) ) PARTITION BY LIST (country); CREATE TABLE users_ru PARTITION OF users_part FOR VALUES IN ('RU'); CREATE TABLE users_us PARTITION OF users_part FOR VALUES IN ('US'); CREATE TABLE users_gb PARTITION OF users_part FOR VALUES IN ('GB'); CREATE TABLE users_de PARTITION OF users_part FOR VALUES IN ('DE'); CREATE TABLE users_fr PARTITION OF users_part FOR VALUES IN ('FR'); CREATE TABLE users_jp PARTITION OF users_part FOR VALUES IN ('JP'); CREATE TABLE users_uk PARTITION OF users_part FOR VALUES IN ('UK'); CREATE TABLE users_kz PARTITION OF users_part FOR VALUES IN ('KZ'); -- сделал insert который попросил сгенерировать нейронку EXPLAIN ANALYZE SELECT * FROM users_part WHERE country = 'RU' -- запрос скаинровал только партицию users_ru EXPLAIN ANALYZE SELECT * FROM users_part WHERE country IN ('RU', 'KZ') -- запрос сканировал только партиции users_ru и users_kz EXPLAIN ANALYZE SELECT * FROM users_part WHERE age BETWEEN 44 AND 66; -- сканировал не просто users_part, а каждую партицию по отдельности -- Задание 5. HASH‑партиции по user_id в логах DROP TABLE IF EXISTS user_logs_part; CREATE TABLE user_logs_part ( id int8, user_id bigint NOT NULL, created_at timestamp NOT null, event_type text NOT NULL, payload jsonb, PRIMARY KEY (id, user_id) ) PARTITION BY hash (user_id) CREATE TABLE user_logs_p1 PARTITION OF user_logs_part FOR VALUES WITH (modulus 4, remainder 0); CREATE TABLE user_logs_p2 PARTITION OF user_logs_part FOR VALUES WITH (modulus 4, remainder 1); CREATE TABLE user_logs_p3 PARTITION OF user_logs_part FOR VALUES WITH (modulus 4, remainder 2); CREATE TABLE user_logs_p4 PARTITION OF user_logs_part FOR VALUES WITH (modulus 4, remainder 3); -- сделал insert который попросил сгенерировать нейронку EXPLAIN ANALYZE SELECT * FROM user_logs_part WHERE user_id = 228; -- читает только user_logs_p2 EXPLAIN ANALYZE SELECT * FROM user_logs_part WHERE created_at >= current_date - INTERVAL '7 days'; -- читает все партиции -- Задание 6 -- email, чтобы искать пользователя быстрее, created_at для сортировки и where CREATE UNIQUE INDEX idx_users_ru_email ON users_ru(email); CREATE INDEX idx_users_ru_created_at ON users_ru(created_at); CREATE UNIQUE INDEX idx_users_us_email ON users_us(email); CREATE INDEX idx_users_us_created_at ON users_us(created_at); CREATE UNIQUE INDEX idx_users_gb_email ON users_gb(email); CREATE INDEX idx_users_gb_created_at ON users_gb(created_at); CREATE UNIQUE INDEX idx_users_de_email ON users_de(email); CREATE INDEX idx_users_de_created_at ON users_de(created_at); CREATE UNIQUE INDEX idx_users_fr_email ON users_fr(email); CREATE INDEX idx_users_fr_created_at ON users_fr(created_at); CREATE UNIQUE INDEX idx_users_jp_email ON users_jp(email); CREATE INDEX idx_users_jp_created_at ON users_jp(created_at); CREATE UNIQUE INDEX idx_users_uk_email ON users_uk(email); CREATE INDEX idx_users_uk_created_at ON users_uk(created_at); CREATE UNIQUE INDEX idx_users_kz_email ON users_kz(email); CREATE INDEX idx_users_kz_created_at ON users_kz(created_at); -- должны ускориться запросы с поиском пользователей по email, и запросы с сортировкой по дате или с фильтрацией по интервалам