├── .gitignore ├── Dockerfile ├── Makefile ├── README.md └── init.sql /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/**/* -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM postgres:14 2 | ENV POSTGRES_PASSWORD=postgres 3 | ADD init.sql /docker-entrypoint-initdb.d/ -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | rebuild_restart_db: 2 | docker rm -f my_db 3 | docker build -t my_db . 4 | docker run --name my_db -p 5433:5432 my_db -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Домашнее задание по разработке БД PostgreSQL 2 | 3 | 1. Посмотрите содержимое Dockerfile и init.sql 4 | 2. Соберите докер-образ БД: `docker build -t my_db .` 5 | 3. Запустите докер-контейнер БД: `docker run --name my_db -p 5433:5432 my_db` 6 | 4. Откройте соединение в БД любым удобным вам инструментом. Локальный порт 5433, логин postgres, пароль postgres 7 | 8 | #### Ответьте на следующие вопросы в тесте: 9 | 1. Посмотрите план запроса `select * from bills`. Сколько партиций попало в план? 10 | 2. Посмотрите план запроса `select * from bills where create_dtime >= '2021-10-01' and create_dtime < '2021-12-01'`. Сколько партиций попало в план? 11 | Подсказка: Посмотрите, какие именно партиции попали в план. Если увидите сентябрь, то посмотрите на таймзоны партиций и фильтров. 12 | 3. Посмотрите план запроса `select * from bills where currency = 'USD'`. Индекс по currency используется? Если нет, то почему? 13 | 4. Посмотрите план запроса `select * from bills where currency = 'RUR'`. Индекс по currency используется? Если нет, то почему? 14 | 5. Если предположить, что значения currency равномерно распределены, есть ли смысл в индексе по currency? Если нет, то почему? 15 | 16 | _Мне важно знать, как вам зашла эта домашка. Оставьте, пожалуйста, обратную связь: [https://forms.gle/3eCNJm5pGxzbsa2FA](https://forms.gle/3eCNJm5pGxzbsa2FA). 17 | Заполнение формы займет у вас 3 минуты. Благодаря этому я смогу учесть в будущем хорошие практики и избежать повторения ошибок._ 18 | 19 | #### Задание со звездочкой - смотрим блокировки 20 | 1. Запустите параллельно три сессии 21 | 2. Установите в вашем клиенте manual commit mode. Transaction Isolation Level оставьте Read Commited. 22 | 3. В одной сессии выполните, но не коммитьте 23 | ` 24 | insert into bills(uid, create_dtime, amount, currency) 25 | values ('de5d09be-acfe-42f1-940c-f90db3c43a33', '2021-01-01', 100, 'RUR') 26 | ` 27 | 4. Во второй сессии запустите этот же запрос. Увидите, что он "повис" 28 | 5. В третьей сессии выполните запрос: 29 | ` 30 | select * from pg_stat_activity 31 | join pg_locks pl on pg_stat_activity.pid = pl.pid 32 | where pg_stat_activity.wait_event_type = 'Lock' 33 | and not transactionid is null 34 | ` 35 | 6. На выбор: закоммитьте запрос в первой сессии или в свободной сессии вызовите `select pg_cancel_backend(pid первой сессии)` -------------------------------------------------------------------------------- /init.sql: -------------------------------------------------------------------------------- 1 | -- Установим расширение, нужное для UUID 2 | create extension "uuid-ossp"; 3 | 4 | -- Создадим enum валют 5 | create type t_currency as enum ('RUR','EUR','USD'); 6 | 7 | -- Создадим партиционированную таблицу 8 | create table bills( 9 | id bigserial, -- автоинкрементный id 10 | uid uuid default uuid_generate_v4(), -- автогенерируемый uuid вида de5d09be-acfe-42f1-940c-f90db3c43a31 11 | create_dtime timestamptz default now(), -- дата счета, по ней партиционируем 12 | amount float8 not null, -- сумма счета 13 | currency t_currency not null, -- валюта счета, тип enum 14 | merchant_payload jsonb -- неструктурированный json от продавца 15 | ) partition by range (create_dtime); -- партиционируем по диапазону дат 16 | 17 | -- Ограничения уникальности должны включать ключ партиционирования, чтобы обеспечить сквозную уникальность для всех партиций 18 | -- Добавим первичный ключ 19 | alter table bills add primary key (id, create_dtime); 20 | -- Добавим ограничение уникальности uid 21 | create unique index on bills(uid, create_dtime); 22 | 23 | create index on bills(currency); 24 | 25 | -- Создадим партиции. Руками неудобно, правда? 26 | -- А еще можно забыть... 27 | create table bills_p202101 partition of bills for values from ('2021-01-01') to ('2021-02-01'); 28 | create table bills_p202102 partition of bills for values from ('2021-02-01') to ('2021-03-01'); 29 | create table bills_p202103 partition of bills for values from ('2021-03-01') to ('2021-04-01'); 30 | create table bills_p202104 partition of bills for values from ('2021-04-01') to ('2021-05-01'); 31 | create table bills_p202105 partition of bills for values from ('2021-05-01') to ('2021-06-01'); 32 | create table bills_p202106 partition of bills for values from ('2021-06-01') to ('2021-07-01'); 33 | create table bills_p202107 partition of bills for values from ('2021-07-01') to ('2021-08-01'); 34 | create table bills_p202108 partition of bills for values from ('2021-08-01') to ('2021-09-01'); 35 | create table bills_p202109 partition of bills for values from ('2021-09-01') to ('2021-10-01'); 36 | create table bills_p202110 partition of bills for values from ('2021-10-01') to ('2021-11-01'); 37 | create table bills_p202111 partition of bills for values from ('2021-11-01') to ('2021-12-01'); 38 | create table bills_p202112 partition of bills for values from ('2021-12-01') to ('2022-01-01'); 39 | 40 | -- Заполним таблицу данными 41 | insert into bills(create_dtime, amount, currency, merchant_payload) 42 | select generate_series as timestamp, 100, 'RUR', ('{"orderId": "123"}')::jsonb 43 | from generate_series('2021-01-01', '2021-12-31', interval '1 hour'); 44 | 45 | -- Соберем статистику после заполнения таблицы, чтобы планировщик строил корректные планы. Обычно вам это не нужно. 46 | analyze bills; --------------------------------------------------------------------------------