Files
netology-devops/src/homework/06-database/6.2/readme.md
2022-06-08 10:33:14 +07:00

14 KiB
Raw Blame History

Выполнение домашнего задания по теме "6.2. SQL".

Q/A

Задача 1

Используя docker поднимите инстанс PostgreSQL (версию 12) c 2 volume, в который будут складываться данные БД и бэкапы.

Приведите получившуюся команду или docker-compose манифест.

Описание сервиса postgresql в файле docker-compose.yml.

Задача 2

В БД из задачи 1:

  • создайте пользователя test-admin-user и БД test_db
  • в БД test_db создайте таблицу orders и clients (спeцификация таблиц ниже)
  • предоставьте привилегии на все операции пользователю test-admin-user на таблицы БД test_db
  • создайте пользователя test-simple-user
  • предоставьте пользователю test-simple-user права на SELECT/INSERT/UPDATE/DELETE данных таблиц БД test_db

Таблица orders:

  • id (serial primary key)
  • наименование (string)
  • цена (integer)

Таблица clients:

  • id (serial primary key)
  • фамилия (string)
  • страна проживания (string, index)
  • заказ (foreign key orders)

Приведите:

  • итоговый список БД после выполнения пунктов выше,
  • описание таблиц (describe)
  • SQL-запрос для выдачи списка пользователей с правами над таблицами test_db
  • список пользователей с правами над таблицами test_db

В рамках выполнения задачи 1 через переменные окружения (POSTGRES_DB: test_db) было проставлено название базы данных, которую необходимо создать при первом запуске контейнера. Таким образом, вручную создавать данную БД не нужно.

Но если необходимо создать ещё одну базу данных, то это можно сделать следующими командами:

docker-compose exec postgres sh
createdb --username=admin some_db

Далее создадим пользователей. Для начала подключимся к БД с помощью утилиты psql:

docker-compose exec postgres psql --username=admin --dbname=test_db

Затем выполним следующие sql-команды:

CREATE USER "test-admin-user" WITH PASSWORD '123';
CREATE USER "test-simple-user" WITH PASSWORD '123';

После этого, создадим таблицы. Скрипты для создания таблиц в БД: migration_structure.sql.

Следующим шагом, дадим права новым пользователям:

GRANT ALL PRIVILEGES ON DATABASE "test_db" to "test-admin-user";
REVOKE ALL PRIVELEGES ON ON DATABASE "test_db" from "test-simple-user";
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA "public" to "test-simple-user";
  • итоговый список БД после выполнения пунктов выше
test_db-# \l
                                  List of databases
   Name    | Owner | Encoding |  Collate   |   Ctype    |      Access privileges      
-----------+-------+----------+------------+------------+-----------------------------
 postgres  | admin | UTF8     | en_US.utf8 | en_US.utf8 | 
 some_db   | admin | UTF8     | en_US.utf8 | en_US.utf8 | 
 template0 | admin | UTF8     | en_US.utf8 | en_US.utf8 | =c/admin                   +
           |       |          |            |            | admin=CTc/admin
 template1 | admin | UTF8     | en_US.utf8 | en_US.utf8 | =c/admin                   +
           |       |          |            |            | admin=CTc/admin
 test_db   | admin | UTF8     | en_US.utf8 | en_US.utf8 | =Tc/admin                  +
           |       |          |            |            | admin=CTc/admin            +
           |       |          |            |            | "test-admin-user"=CTc/admin
  • описание таблиц (describe)
test_db=# \dt
        List of relations
 Schema |  Name   | Type  | Owner 
--------+---------+-------+-------
 public | clients | table | admin
 public | orders  | table | admin

test_db=# \d orders
                                    Table "public.orders"
 Column |          Type          | Collation | Nullable |              Default               
--------+------------------------+-----------+----------+------------------------------------
 id     | integer                |           | not null | nextval('orders_id_seq'::regclass)
 name   | character varying(255) |           |          | 
 price  | integer                |           |          | 
Indexes:
    "orders_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "clients" CONSTRAINT "client_order_fk" FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE

test_db=# \d clients
                                     Table "public.clients"
  Column   |          Type          | Collation | Nullable |               Default               
-----------+------------------------+-----------+----------+-------------------------------------
 id        | integer                |           | not null | nextval('clients_id_seq'::regclass)
 last_name | character varying(255) |           |          | 
 country   | character varying(255) |           |          | 
 order_id  | integer                |           |          | 
Indexes:
    "clients_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "client_order_fk" FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE
  • SQL-запрос для выдачи списка пользователей с правами над таблицами test_db
SELECT 
    table_schema, table_catalog, table_name, grantee, privilege_type
FROM information_schema.table_privileges
WHERE table_catalog like 'test_db';
  • список пользователей с правами над таблицами test_db
"PUBLIC"
"admin"
"test-simple-user"

Задача 3

Используя SQL синтаксис - наполните таблицы следующими тестовыми данными:

Таблица orders

Наименование цена
Шоколад 10
Принтер 3000
Книга 500
Монитор 7000
Гитара 4000

Таблица clients

ФИО Страна проживания
Иванов Иван Иванович USA
Петров Петр Петрович Canada
Иоганн Себастьян Бах Japan
Ронни Джеймс Дио Russia
Ritchie Blackmore Russia

Используя SQL синтаксис:

  • вычислите количество записей для каждой таблицы
  • приведите в ответе:
    • запросы
    • результаты их выполнения.

Скрипты заполнения таблиц данными: migration_data.sql.

Запросы на получение количество записей в таблицах:

-- для таблицы orders
select count(id) from orders;
-- Результат: 5

-- для таблицы clients
select count(id) from clients;
-- Результат: 5

Задача 4

Часть пользователей из таблицы clients решили оформить заказы из таблицы orders.

Используя foreign keys свяжите записи из таблиц, согласно таблице:

ФИО Заказ
Иванов Иван Иванович Книга
Петров Петр Петрович Монитор
Иоганн Себастьян Бах Гитара

Приведите SQL-запросы для выполнения данных операций.

Приведите SQL-запрос для выдачи всех пользователей, которые совершили заказ, а также вывод данного запроса.

Подсказка - используйте директиву UPDATE.

Запросы на проставление связи между клиентами и заказами:

update clients 
set order_id = (
    select id
    from orders
    where orders.name like 'Книга'
) 
where clients.last_name like 'Иванов Иван Иванович';

update clients 
set order_id = (
    select id
    from orders
    where orders.name like 'Монитор'
) 
where clients.last_name like 'Иванов Иван Иванович';

update clients 
set order_id = (
    select id
    from orders
    where orders.name like 'Гитара'
) 
where clients.last_name like 'Иоганн Себастьян Бах';

Запрос на вывод всех пользователей, которые совершили заказ:

select * from clients where order_id is not null;

Результат данного запроса:

id last_name country order_id
1 Иванов Иван Иванович USA 3
2 Петров Петр Петрович Canada 4
3 Иоганн Себастьян Бах Japan 5

Задача 5

Получите полную информацию по выполнению запроса выдачи всех пользователей из задачи 4 (используя директиву EXPLAIN).

Приведите получившийся результат и объясните что значат полученные значения.

Запрос на получение анализа запроса из задачи 4:

explain select * from clients where order_id is not null;

Результат выполнения:

"QUERY PLAN"
"Seq Scan on clients  (cost=0.00..10.70 rows=70 width=1040)"
"  Filter: (order_id IS NOT NULL)"

Данный результат можно проанализировать следующим образом:

  • Seq Scan on clients - последовательное сканирование всех записей в таблице (простой перебор записей).
  • cost=0.00 - приблизительная стоимость запуска запроса. Это время, которое проходит, прежде чем начнётся этап вывода данных.
  • ..10.70 - приблизительная общая стоимость запроса. Определяется наихудший вариант выполнения, когда необходимо проанализировать и вывести все строки в таблице.
  • rows=70 - ожидаемое число строк, которое вернёт запрос в наихудшем варианте выполнения.
  • width=1040 - ожидаемый средний размер строк, которые отдаст запрос (в байтах).
  • Filter: (order_id IS NOT NULL) - применение фильтра на проверку на null. В данном случае фильтр будет применён к каждой записи из таблицы.

Подробнее про использование EXPLAIN

Задача 6

Создайте бэкап БД test_db и поместите его в volume, предназначенный для бэкапов (см. Задачу 1).

Остановите контейнер с PostgreSQL (но не удаляйте volumes).

Поднимите новый пустой контейнер с PostgreSQL.

Восстановите БД test_db в новом контейнере.

Приведите список операций, который вы применяли для бэкапа данных и восстановления.

Создание бэкапа базы данных:

docker-compose exec postgres sh
pg_dump -Uadmin -dtest_db > test_db.sql

Остановка текущего контейнера с БД и запуск нового:

docker-compose stop postgres
docker run --rm -d --name=netology_dump_postgres \
  -e POSTGRES_USER=admin \
  -e POSTGRES_PASSWORD=123 \
  -v 62_netology_pgdump:/opt/pgdump -w /opt/pgdump \
  postgres:12.11-alpine

Применение дампа в новом инстансе БД:

docker exec -it netology_dump_postgres sh
psql -Uadmin -c"CREATE DATABASE test_db;"
psql -Uadmin -dtest_db < test_db.sql
psql -Uadmin -dtest_db

test_db=# \l
   Name    | Owner | Encoding |  Collate   |   Ctype    | Access privileges 
-----------+-------+----------+------------+------------+-------------------
 admin     | admin | UTF8     | en_US.utf8 | en_US.utf8 | 
 postgres  | admin | UTF8     | en_US.utf8 | en_US.utf8 | 
 template0 | admin | UTF8     | en_US.utf8 | en_US.utf8 | =c/admin         +
           |       |          |            |            | admin=CTc/admin
 template1 | admin | UTF8     | en_US.utf8 | en_US.utf8 | =c/admin         +
           |       |          |            |            | admin=CTc/admin
 test_db   | admin | UTF8     | en_US.utf8 | en_US.utf8 | 

test_db=# \dt
        List of relations
 Schema |  Name   | Type  | Owner 
--------+---------+-------+-------
 public | clients | table | admin
 public | orders  | table | admin