Скачать и запустить демонстрационную базу данных с сайта PostgresPRO. Выполните следующие запросы:
- Вывести какие модели самолётов летают в Уфу
- Среднее количество людей на рейсах из Санкт-Петербурга в Москву
- Найти модель самолета с максимальным количеством сидений (учитывается что таких моделей может быть несколько)
- Вывести рейсы число мест в которых больше чем проданных на них билетов
- Вывести общую сумму потраченные на билеты каждым пассажиром
- На каких местах сидел пассажир летающий чаще всего?
- Выведите таблицу самолетов отсортированных по убыванию количества мест с дополнительным атрибутом, в котором самолёты
- пронумерованы по частоте полётов.
Задание 1:
- Создайте новую базу данных в PostgreSQL включающие две таблицы: "accounts" и "transactions". Таблица "accounts" должна содержать следующие поля: id (уникальный идентификатор), name (имя), balance (баланс). Таблица "transactions" должна содержать следующие поля: id (уникальный идентификатор), account_id (ссылка на id в таблице "accounts"), amount ( сумма).
- Проведите проверку что PostgreSQL не допускается аномалия грязного чтения, объясните почему.
- Проверьте, что на уровне изоляции Read Committed не предотвращается аномалия фантомного чтения.
- Начните транзакцию с уровнем изоляции Repeatable Read(и пока не выполняйте в ней никаких команд). В другом сеансе удалите строку и зафиксируйте изменения. Видна ли строка в открытой транзакции? Что изменится, если в начале транзакции выполнить запрос,но не обращаться в нем ни к одной таблице?
- Напишите функцию, которая позволяет выполнить перевод средств с одного счета на другой, используя транзакции. Функция должна использовать уровень изоляции транзакции "Serializable". Протестируйте функцию с использованием нескольких параллельных сеансов, чтобы убедиться, что переводы не могут быть выполнены дважды.
- Начните транзакцию Repeatable Read и выполните какой-нибудь запрос. В другом сеансе создайте таблицу. Видно ли в первой транзакции описание таблицы в системном каталоге? Можно ли в ней прочитать строки таблицы?
- Убедитесь, что команда DROP TABLE транзакционна.
Задание 2:
-
Установите расширение pageinspect. Создать базу данных с именем versions_db. Создать таблицу users со следующими полями: id: уникальный идентификатор пользователя (integer, primary key, auto-increment). username: имя пользователя (varchar(255)). email: электронный адрес пользователя (varchar(255)). version: версия строки (integer).
-
Создать триггер, который будет автоматически увеличивать поле version строки при любом обновлении.
-
Вставить в таблицу users строку с различными данными а затем обновите.
-
При помощи следующего запроса:
SELECT '(0,' || lp || ')' AS ctid, t_xmin as xmin, t_xmax as xmax, CASE WHEN (t_infomask & 256) > 0 THEN 't' END AS xmin_c, CASE WHEN (t_infomask & 512) > 0 THEN 't' END AS xmin_a, CASE WHEN (t_infomask & 1024) > 0 THEN 't' END AS xmax_c, CASE WHEN (t_infomask & 2048) > 0 THEN 't' END AS xmax_a FROM heap_page_items(get_raw_page('users', 0)) ORDER BY lp;
Где, ctid является ссылкой на следующую, более новую, версию той же строки. У самой новой, актуальной, версии строки ctid ссылается на саму эту версию xmin и xmax определяют видимость данной версии строки в терминах начального и конечного номеров транзакций. xmin_c, xmin_a, xmax_c, xmax_a содержит ряд битов, определяющих свойства данной версии
-
Выведите информацию о версиях строк, узнав сколько версий строк щас находится в таблице и сравнить их с атрибутом ( version)
- Опустошим таблицу при помощи TRUNCATE;
- Начините транзакцию и вставьте новую строку и узнайте номер текущий транзакции (это можно сделать при помощи след команды: INSERT INTO users(...) VALUES (...) RETURNING *, ctid, xmin, xmax;
- Поставьте точку сохранения и добавьте новую строку использовав команду из пункта 7.
- Откатимся к точке сохранения и добавим новую строчку аналогично 7 и 8 пункту.
- Выведите сведения о версиях строк.
Задание 3:
-
Создать таблицу t с полями id(integer) и name (char(2000)) с параметром filfactor = 75%.
-
Создать индекс над полем t(name)
-
Установите расширение pageinspect.
-
Создать представление которое будет включать в себя информацию о версиях строк при помощью след запроса:
CREATE VIEW t_v AS SELECT '(0,' || lp || ')' AS ctid, CASE lp_flags WHEN 0 THEN 'unused' WHEN 1 THEN 'normal' WHEN 2 THEN 'redirect to ' || lp_off WHEN 3 THEN 'dead' END AS state, t_xmin || CASE WHEN (t_infomask & 256) > 0 THEN ' (c)' WHEN (t_infomask & 512) > 0 THEN ' (a)' ELSE '' END AS xmin, t_xmax || CASE WHEN (t_infomask & 1024) > 0 THEN ' (c)' WHEN (t_infomask & 2048) > 0 THEN ' (a)' ELSE '' END AS xmax, CASE WHEN (t_infomask2 & 16384) > 0 THEN 't' END AS hhu, CASE WHEN (t_infomask2 & 32768) > 0 THEN 't' END AS hot, t_ctid FROM heap_page_items(get_raw_page('t', 0)) ORDER BY lp;
флаг Heap Hot Updated показывает, что надо идти по цепочке ctid, флаг Heap Only Tuple показывает, что на данную версию строки нет ссылок из индексов.
-
Спроецировать ситуацию в таблице t, при которой произойдет внутристраничная очистка без участия HOT-обновлений.
-
После воспроизвести ситуацию но уже с HOT-обновлением
★ Использовать фактор заполнения на 80% и на 50%, указать в отчете в чем разница между разными факторами. Какой лучше всего фактор заполнения использовать для этой практики?
Задание 1.
-
Создать базу данных с именем vacuum_db.
-
Создать таблицу users, отключив параметр автоочистки (CREATE TABLE ... WITH (autovacuum_enabled = off);), со следующими полями:
id: уникальный идентификатор пользователя (integer, primary key, auto-increment). username: имя пользователя (varchar(255)). email: электронный адрес пользователя (varchar(255)). category: категория (char(3))
-
Написать скрипт заполняющий таблицу users 1000000 рандомными записями, в поле category всегда должна находиться запись ‘FOO’.
-
Используя оператор Explain выведите из таблицы users все записи которые в поле category имеют значение ‘FOO’;
-
Выполните команду ANALYZE;
-
Используя оператор Explain выведите из таблицы users все записи которые в поле category имеют значение ‘FOO’;
-
Отличаются ли методы доступа к данным и почему
-
Временно уменьшите значение maintenance_work_mem чтоб оно стало равно 1MB (не забудьте выполнить функцию pg_reload_conf())
-
Измените значение поля category на ‘BPP’
-
Запустите очистку VACUUM VERBOSE. Заодно через небольшое время в другом сеансе обратитесь к pg_stat_progress_vacuum.
-
Верните значение maintenance_work_mem к исходному значению.
Задание 2.
- Узнать текущий размер файла данных таблицы users при помощи функции: pg_size_pretty(pg_table_size('название таблицы'))
- Удалите 90% случайных строк (Случайность важна, чтобы в каждой странице остались какие-нибудь не удаленные строки)
- Выполните очистку
- Ещё раз узнайте текущий размер файла данных таблицы users и сравните его с первым пунктом. Объясните результат
- Заново заполните таблицу и повторите пункты 1 и 2.
- Выполните полную очистку
- Ещё раз узнайте текущий размер файла данных таблицы users и сравните его с результатом пункта 5. Объясните результат
Задание 3.
- Включите параметр автоочистки в таблице users
- Настройте автоочистку на запуск при изменении 10 % строк, время «сна» — одна секунда (autovacuum_vacuum_threshold = 0,
- autovacuum_vacuum_scale_factor = 0.1, autovacuum_naptime = '1s')
- Заполните таблицу users до 1000000 записей
- Узнать текущий размер файла данных таблицы users при помощи функции: pg_size_pretty(pg_table_size('название таблицы'))
- Напишите скрипт который двадцать раз с интервалом в несколько секунд изменяет по 5 % случайных строк. Каждое изменение
- выполняйте в отдельной транзакции.
- При помощи pg_stat_all_tables узнайте сколько раз выполнялась автоочистка (autovacuum_count)
- Сравнить размеры таблицы до и после обновлений
- Совпадают ли результаты с ожидаемыми и как их объяснить?