# Домашнее задание к занятию "6.4. PostgreSQL" ## Задача 1 Используя docker поднимите инстанс PostgreSQL (версию 13). Данные БД сохраните в volume. Подключитесь к БД PostgreSQL используя psql. Воспользуйтесь командой \? для вывода подсказки по имеющимся в psql управляющим командам. Найдите и приведите управляющие команды для: 1. вывода списка БД 1. подключения к БД 1. вывода списка таблиц 1. вывода описания содержимого таблиц 1. выхода из psql ## Ответ 1 Запустил так: `docker run --name postgres09 -e POSTGRES_HOST_AUTH_METHOD=trust -v C:\Users\vah\docker\09-postgre\db:/var/lib/postgresql/data -v C:\Users\vah\docker\09-postgre\tmp:/tmp/backup -d postgres` Подключаюсь так: `docker exec -it postgres09 psql -U postgres` 1. `\l[+] [PATTERN] list databases` 2. `\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}` ` connect to new database (currently "postgres")` 3. `\d[S+] list tables, views, and sequences` **или** `\dt[S+] [PATTERN] list tables` 4. `\dS+` или `\dtS+` 5. `\q` ## Задача 2 Используя `psql` создайте БД `test_database`. Изучите [бэкап БД](https://github.com/netology-code/virt-homeworks/tree/master/06-db-04-postgresql/test_data). Восстановите бэкап БД в `test_database`. Перейдите в управляющую консоль `psql` внутри контейнера. Подключитесь к восстановленной БД и проведите операцию ANALYZE для сбора статистики по таблице. Используя таблицу [pg_stats](https://postgrespro.ru/docs/postgresql/12/view-pg-stats) столбец таблицы `orders` с наибольшим средним значением размера элементов в байтах. **Приведите в ответе** команду, которую вы использовали для вычисления и полученный результат. ## Ответ 2 ``` CREATE DATABASE test_database; \c test_database \i /tmp/backup/test_dump.sql test_database=# ANALYZE VERBOSE public.orders; INFO: analyzing "public.orders" INFO: "orders": scanned 1 of 1 pages, containing 8 live rows and 0 dead rows; 8 rows in sample, 8 estimated total rows ANALYZE SELECT tablename, attname, avg_width FROM pg_stats WHERE tablename='orders' ORDER BY avg_width DESC LIMIT 1; tablename | attname | avg_width -----------+---------+----------- orders | title | 16 (1 row) ``` ## Задача 3 Архитектор и администратор БД выяснили, что ваша таблица orders разрослась до невиданных размеров и поиск по ней занимает долгое время. Вам, как успешному выпускнику курсов DevOps в нетологии предложили провести разбиение таблицы на 2 (шардировать на orders_1 - price>499 и orders_2 - price<=499). Предложите SQL-транзакцию для проведения данной операции. Можно ли было изначально исключить "ручное" разбиение при проектировании таблицы orders? ## Ответ 3 Провести разбиение: ``` CREATE TABLE orders_1 (CHECK (price < 499)) INHERITS (orders); CREATE TABLE orders_2 (CHECK (price >= 499)) INHERITS (orders); ``` При необходимости перенести данные из основной таблицы в созданные (если этого не сделать - новые данные будут записываться в новые, а старые останутся на месте) ``` INSERT INTO orders_1 SELECT * FROM orders WHERE price < 499; DELETE FROM only orders WHERE price < 499; INSERT INTO orders_2 SELECT * FROM orders WHERE price >= 499; DELETE FROM only orders WHERE price >= 499; ``` Изначально можно было создать такую таблицу: ``` CREATE TABLE public.orders_new ( id integer NOT NULL, title character varying(80) NOT NULL, price integer DEFAULT 0 ) PARTITION BY RANGE (price); ``` И дополнительно таблицы: ``` CREATE TABLE orders_new1 PARTITION OF orders_new FOR VALUES FROM ('0') TO ('499'); CREATE TABLE orders_new2 PARTITION OF orders_new FOR VALUES FROM ('499') TO ('999'); ``` Правда в этом случае не получится добавить товар с ценой больше 999, и как создать таблицу для всего "больше 999" я найти не смог :) Ещё нашёл мощную штуку - https://github.com/pgpartman/pg_partman Похоже при огромных объёмах она оченеь помочь может :) ## Задача 4 Используя утилиту `pg_dump` создайте бекап БД `test_database`. Как бы вы доработали бэкап-файл, чтобы добавить уникальность значения столбца `title` для таблиц `test_database`? ## Ответ 4 Добавил бы слово **UNIQUE**. ``` CREATE TABLE public.orders ( id integer NOT NULL, title character varying(80) UNIQUE NOT NULL, price integer DEFAULT 0 ); ```