← Back to course

Backup, restore и базовое обслуживание: защищаем данные PostgreSQL

Backup, restore и базовое обслуживание: защищаем данные PostgreSQL

Возвращаемся к PostgreSQL.

В предыдущем уроке ты изучил, как PostgreSQL подключается к реальным приложениям.

Ты узнал про:

Очень хорошо.

Теперь твоя база данных может работать с реальными приложениями.

Это мощно.

Но сила приносит ответственность.

И иногда панику.

Потому что когда приложение начинает хранить реальные данные, один вопрос становится очень важным:

Что будет, если что-то пойдёт не так?

Таблицу удалили.

Сервер упал.

Плохая migration запустилась.

Разработчик написал DELETE без WHERE.

Ноутбук умер.

Диск сломался.

Кто-то говорит:

Я изменил только одну маленькую вещь.

Очень опасная фраза.

Сегодня мы поговорим про backup, restore и базовое обслуживание.

Это не самая гламурная часть баз данных.

Никто не открывает курс PostgreSQL и не говорит:

Я не могу дождаться стратегии backup-ов.

Но backup-и скучные только до того дня, когда они тебе нужны.

Потом они становятся прекрасными.

Как парашют.

Не очень интересный во время обычной прогулки.

Очень важный во время падения.

Что ты изучишь

В этом уроке ты изучишь:

К концу этого урока ты поймёшь, как защищать свои данные PostgreSQL.

Потому что создавать данные — хорошо.

Использовать данные — полезно.

Терять данные — формирует характер.

Но давай избегать чрезмерного формирования характера.

Почему backup-и важны

Backup — это копия твоей базы данных, которую можно использовать, если что-то пойдёт не так.

Простая идея.

Очень важная.

Без backup-ов потеря данных может быть навсегда.

Примеры проблем:

Кто-то случайно удалил строки.
Migration сломала таблицы.
Диск сервера сломался.
База данных повредилась.
Неправильная команда удалила таблицу.
Deploy пошёл плохо.
Production база была перезаписана.

Некоторые из этих ситуаций звучат драматично.

Некоторые звучат глуповато.

В реальной жизни случаются обе.

Компьютеры ломаются.

Люди ошибаются.

Разработчики ошибаются творчески.

Backup даёт путь назад.

Это не магия.

Но это надежда в виде файла.

Backup не настоящий, пока restore не работает

Очень важное правило:

Backup, который ты никогда не тестировал, — это только теория.

У тебя может быть backup-файл.

Но можешь ли ты его восстановить?

Содержит ли он те данные, которые ты ожидаешь?

Он полный?

Он не слишком старый?

Не требует ли он пароль, который ты забыл?

Восстанавливается ли он в рабочую базу данных?

Если ты этого не знаешь, у тебя на самом деле нет стратегии backup.

У тебя есть талисман на удачу.

А PostgreSQL талисманы не впечатляют.

Поэтому всегда помни:

Backup — это первый шаг.
Тест restore — это второй шаг.

Оба важны.

Подготовь demo database

Открой PostgreSQL:

sudo -iu postgres psql

Создай demo database:

CREATE DATABASE backup_demo_db;

Подключись к ней:

\c backup_demo_db

Создай таблицу:

CREATE TABLE notes (
  id SERIAL PRIMARY KEY,
  title VARCHAR(150) NOT NULL,
  content TEXT,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Добавь немного данных:

INSERT INTO notes (title, content)
VALUES
  ('First Note', 'This is the first note.'),
  ('Backup Note', 'This row should survive backup and restore.'),
  ('PostgreSQL Note', 'Databases remember things. Sometimes too well.');

Проверь данные:

SELECT * FROM notes;

Теперь у нас есть маленькая база данных для backup.

Это не очень важные данные.

Но хорошие для практики.

Практикуйся на фейковых данных.

Не на production.

Production — это не детская площадка.

Production — это место, где маленькие ошибки носят дорогие ботинки.

Что такое pg_dump?

pg_dump — это инструмент PostgreSQL, который создаёт backup базы данных.

Он может экспортировать:

структуру таблиц
данные
индексы
constraints
sequences
объекты базы данных

По умолчанию он не делает backup всего PostgreSQL server.

Он делает backup одной базы данных.

Базовая идея:

pg_dump читает базу данных и записывает backup-файл.

pg_dump запускается из terminal.

Не внутри psql.

Это важно.

Внутри psql ты пишешь SQL-команды.

В terminal ты запускаешь инструменты:

pg_dump
psql
createdb
dropdb
pg_restore

Разные места.

Разные инструменты.

То же базоданное приключение.

Создаём простой SQL backup

Сначала выйди из psql:

\q

Теперь запусти это из terminal:

pg_dump -U postgres -d backup_demo_db > backup_demo_db.sql

Это создаст файл:

backup_demo_db.sql

Это простой SQL backup.

Он содержит SQL-команды, которые могут восстановить структуру и данные базы.

Можешь его посмотреть:

less backup_demo_db.sql

Там можно увидеть команды типа:

CREATE TABLE
COPY
ALTER TABLE
CREATE SEQUENCE

Простой SQL backup читается человеком.

Это приятно.

Его можно восстановить через psql.

Просто.

Полезно.

Очень хорошо для начинающих.

Backup с host и port

Иногда нужно указать host и port:

pg_dump -h localhost -p 5432 -U postgres -d backup_demo_db > backup_demo_db.sql

Это означает:

-h localhost       подключиться к localhost
-p 5432            использовать port 5432
-U postgres        подключиться как пользователь postgres
-d backup_demo_db  сделать backup этой базы

Если используешь пользователя приложения, замени postgres на этого пользователя.

Пример:

pg_dump -h localhost -p 5432 -U app_user -d app_db > app_db.sql

Пользователь должен иметь право читать базу данных.

PostgreSQL не может сделать backup того, что пользователь не может видеть.

Очень справедливо.

Очень строго.

Очень PostgreSQL.

Восстанавливаем простой SQL backup

Теперь восстановим backup в новую базу данных.

Создай новую базу:

createdb -U postgres backup_demo_restore_db

Теперь восстанови:

psql -U postgres -d backup_demo_restore_db < backup_demo_db.sql

Это читает SQL-файл и выполняет его в новой базе.

Теперь подключись:

psql -U postgres -d backup_demo_restore_db

Проверь данные:

SELECT * FROM notes;

Ты должен увидеть строки.

Хорошо.

Ты создал backup.

Ты его восстановил.

Ты его протестировал.

Это правильный путь.

Backup без теста restore — это театр уверенности.

Тест restore — это реальность.

Реальность имеет значение.

Раздражает, но правда.

Пример DROP и restore

Давай симулируем катастрофу.

Подключись к восстановленной базе:

psql -U postgres -d backup_demo_restore_db

Удали таблицу:

DROP TABLE notes;

Теперь проверь:

SELECT * FROM notes;

PostgreSQL пожалуется:

relation "notes" does not exist

Очень грустно.

Очень обучающе.

Выйди:

\q

Восстанови снова:

psql -U postgres -d backup_demo_restore_db < backup_demo_db.sql

Если таблица уже существует, можно получить ошибки, если backup не содержит drop-команд.

Для более чистой практики можно пересоздать базу:

dropdb -U postgres backup_demo_restore_db
createdb -U postgres backup_demo_restore_db
psql -U postgres -d backup_demo_restore_db < backup_demo_db.sql

Потом проверь снова:

psql -U postgres -d backup_demo_restore_db
SELECT * FROM notes;

Данные вернулись.

Вот это и есть магическое чувство backup-ов.

Не настоящая магия.

Лучше.

Протестированная процедура.

Создаём backup с --clean

Можно создать backup, который содержит команды для удаления существующих объектов перед их повторным созданием.

Пример:

pg_dump -U postgres --clean --if-exists -d backup_demo_db > backup_demo_clean.sql

Опции:

--clean       добавляет DROP-команды
--if-exists   избегает ошибок, если объекты не существуют

Это может облегчить restore поверх существующей базы.

Но будь осторожен.

Backup с DROP-командами может удалить существующие объекты во время restore.

Возможно, именно этого ты хочешь.

А возможно, так твой день станет очень захватывающим.

Всегда знай, что делает твой backup-файл.

SQL-файлы — это не декорация.

Они выполняются.

PostgreSQL слушается.

Эмоциональная поддержка не входит в комплект.

Backup в custom format

PostgreSQL также поддерживает backup в custom format.

Создай его так:

pg_dump -U postgres -F c -d backup_demo_db -f backup_demo_db.dump

Здесь:

-F c              custom format
-f file_name      output file

Это создаст:

backup_demo_db.dump

Этот файл не является обычным читаемым SQL.

Но он гибкий.

Его восстанавливают через pg_restore.

Custom format полезен, потому что можно:

восстанавливать выбранные таблицы
восстанавливать с большим количеством опций
использовать parallel restore в больших случаях
просматривать содержимое backup

Для многих реальных проектов custom format — хороший выбор.

Менее читаемый.

Более мощный.

Как сжатый ящик инструментов для базы данных.

Восстанавливаем custom format backup

Создай новую базу данных:

createdb -U postgres backup_demo_custom_restore_db

Восстанови через pg_restore:

pg_restore -U postgres -d backup_demo_custom_restore_db backup_demo_db.dump

Теперь подключись:

psql -U postgres -d backup_demo_custom_restore_db

Проверь данные:

SELECT * FROM notes;

Ты должен увидеть свои данные.

Хорошо.

Теперь ты знаешь оба стиля:

простой SQL backup -> restore через psql
custom backup      -> restore через pg_restore

Простое правило.

Очень полезное.

Простой SQL vs custom format

Простой SQL backup:

pg_dump -U postgres -d backup_demo_db > backup_demo_db.sql

Restore:

psql -U postgres -d new_db < backup_demo_db.sql

Хорошо для:

простых backup-ов
обучения
человекочитаемых файлов
маленьких баз данных
лёгкой проверки

Custom format backup:

pg_dump -U postgres -F c -d backup_demo_db -f backup_demo_db.dump

Restore:

pg_restore -U postgres -d new_db backup_demo_db.dump

Хорошо для:

больших баз данных
более гибкого restore
восстановления выбранных объектов
production-style workflow

Оба варианта полезны.

Не превращай это в религиозную войну.

У баз данных и так достаточно драмы.

Просмотр содержимого custom backup

Можно посмотреть custom backup:

pg_restore -l backup_demo_db.dump

Это показывает, что есть внутри backup.

Ты можешь увидеть таблицы, sequences, constraints и data sections.

Это полезно, если хочешь понять, что содержит backup.

Потому что “надеюсь, там есть таблица” — это не стратегия.

Проверь.

Подтверди.

Потом спи спокойнее.

Возможно.

Названия backup-файлов

Используй понятные названия файлов.

Плохо:

backup.sql
new_backup.sql
backup_final.sql
backup_final_REAL.sql
backup_please_work.sql

Хорошо:

backup_demo_db_2026-05-03.sql
shop_db_2026-05-03_22-30.dump
portfolio_db_before_migration_2026-05-03.dump

Добавляй:

название базы данных
дату
время, если полезно
причину, если полезно

Пример:

pg_dump -U postgres -F c -d shop_db -f shop_db_2026-05-03.dump

Хорошие названия спасают мозг.

Плохие названия создают археологию.

А никто не хочет раскапывать backup-файлы в 2 ночи.

Сжимаем простой SQL backup

Простые SQL backup-и могут быть большими.

Их можно сжать:

pg_dump -U postgres -d backup_demo_db | gzip > backup_demo_db.sql.gz

Восстановление сжатого backup:

gunzip -c backup_demo_db.sql.gz | psql -U postgres -d backup_demo_restore_db

Это полезно для экономии места на диске.

Но помни:

Сжатые файлы тоже нужно тестировать.

Сжатый сломанный backup всё равно сломан.

Просто меньше.

Очень эффективная грусть.

Backup перед опасными изменениями

Перед рискованными операциями создай backup.

Примеры рискованных операций:

большая migration
удаление колонок
изменение типов данных
mass update
mass delete
переделка schema
production deploy
импорт внешних данных

Пример backup:

pg_dump -U postgres -F c -d shop_db -f shop_db_before_migration_2026-05-03.dump

Потом делай опасное изменение.

Если что-то пойдёт не так, у тебя есть точка возврата.

Это профессионально.

Это спокойно.

Это способ не войти в историю базы данных плохим способом.

Опасный пример DELETE

Это опасно:

DELETE FROM customers;

Это удаляет все строки из customers.

Возможно, ты имел в виду:

DELETE FROM customers
WHERE id = 5;

Маленькая разница.

Огромный результат.

Перед выполнением опасных команд используй transaction, когда возможно:

BEGIN;

Выполни команду:

DELETE FROM customers
WHERE id = 5;

Проверь:

SELECT * FROM customers;

Если всё правильно:

COMMIT;

Если ошибка:

ROLLBACK;

Transactions могут спасти от некоторых ошибок.

Backup-и могут спасти от больших ошибок.

Оба полезны.

Как ремень безопасности и airbag.

Не выбирай только одно, потому что чувствуешь себя храбрым.

Базовая стратегия backup

Простая backup strategy должна отвечать на вопросы:

Как часто мы делаем backup?
Где мы храним backup-и?
Как долго мы их храним?
Кто имеет доступ к backup-ам?
Как мы делаем restore?
Тестировали ли мы restore?

Для маленького проекта можно делать:

ежедневный backup
хранить последние 7 daily backups
хранить weekly backup в течение 1 месяца
хранить backup-и вне сервера
регулярно тестировать restore

Для более серьёзных проектов нужен более сильный план.

Но даже простой протестированный план намного лучше, чем:

Мне кажется, server provider что-то имеет.

Возможно, имеет.

Возможно, нет.

Возможно, это стоит дополнительно.

Возможно, это никогда не было включено.

Возможно, оно восстанавливает весь server, но не ту одну базу, которая тебе нужна.

Проверь.

Не предполагай.

Предположение — двоюродный брат катастрофы.

Храни backup-и в безопасном месте

Если база данных и backup на одном сервере, а сервер умирает, можно потерять оба.

Плохо.

Лучшие места для backup-ов:

другой сервер
внешнее хранилище
безопасное cloud storage
зашифрованное backup storage
offline copy для важных данных

Минимум — не держи единственный backup рядом с оригинальной базой.

Это как хранить запасной ключ от дома внутри дома, который горит.

Технически запасной.

Практически не очень полезный.

Защищай backup-файлы

Backup-и содержат данные.

Иногда чувствительные данные.

Это означает, что backup-файлы нужно защищать.

Правила:

не выставляй backup-и публично
ограничивай доступ
используй сильные permissions
подумай про encryption
безопасно удаляй старые backup-и
не отправляй database dumps через email бездумно

Backup базы данных может быть таким же чувствительным, как live database.

Иногда даже более чувствительным.

Потому что люди забывают, что он существует.

Атакующие не забывают.

Очень невежливо с их стороны.

Но правда.

Базовое обслуживание: VACUUM

PostgreSQL использует систему, где обновлённые и удалённые строки оставляют старые версии строк.

Это часть того, как PostgreSQL работает с concurrency.

Очень умно.

Но это означает, что PostgreSQL нуждается в уборке.

Эта уборка называется:

VACUUM

Запусти:

VACUUM;

Это очищает dead rows в текущей базе данных.

Большинство PostgreSQL installations имеют autovacuum включённым.

Autovacuum работает автоматически.

Хорошо.

Потому что ручное запоминание всего — это способ, которым люди проигрывают.

Всё равно полезно знать, что делает VACUUM.

Он помогает PostgreSQL держать таблицы здоровыми.

Как уборка мастерской.

Не гламурно.

Очень нужно.

VACUUM ANALYZE

Можно запустить:

VACUUM ANALYZE;

Это делает две вещи:

VACUUM очищает dead row versions.
ANALYZE обновляет planner statistics.

Planner statistics помогают PostgreSQL выбирать хорошие query plans.

Если statistics устарели, PostgreSQL может делать плохие выборы.

Например, использовать неправильный индекс.

Или сканировать слишком много.

Или в целом выглядеть растерянным бухгалтером.

ANALYZE помогает PostgreSQL лучше понимать данные.

База со свежими statistics — более счастливая база.

Наверное.

PostgreSQL не улыбается.

Но производительность может улучшиться.

ANALYZE отдельно

Можно запустить:

ANALYZE;

Это обновляет statistics без vacuum.

Также можно проанализировать одну таблицу:

ANALYZE products;

Это полезно после больших изменений данных.

Пример:

импортировано много строк
удалено много строк
обновлено много строк
изменилось распределение данных

PostgreSQL использует statistics, чтобы решать, как выполнять запросы.

Плохие statistics могут давать плохие plans.

Плохие plans дают медленные queries.

Медленные queries дают грустных разработчиков.

Цепочка понятна.

REINDEX

Индексы иногда могут раздуваться или требовать перестройки.

В PostgreSQL есть:

REINDEX

Пример:

REINDEX DATABASE backup_demo_db;

Или один index:

REINDEX INDEX index_name;

Или одна table:

REINDEX TABLE table_name;

Не запускай REINDEX случайно каждые пять минут.

Это не чистить зубы.

Используй его, когда нужно.

Для начинающих достаточно знать:

REINDEX перестраивает индексы.

В реальном обслуживании нужно понимать, зачем ты это делаешь.

Слепое обслуживание всё равно слепое.

Даже если носит серьёзную шляпу.

Проверяем размер базы данных

Можно проверить размер базы:

SELECT pg_size_pretty(pg_database_size('backup_demo_db'));

Проверить размеры таблиц:

SELECT
  relname AS table_name,
  pg_size_pretty(pg_total_relation_size(relid)) AS total_size
FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC;

Это помогает понять, что занимает место.

Иногда самая большая таблица — это ожидаемо.

Иногда это log table, которую никто не чистил три года.

Базы данных собирают историю.

Иногда слишком много истории.

Как ящик со старыми кабелями.

Проверяем активные подключения

Можно увидеть активные подключения:

SELECT
  pid,
  usename,
  datname,
  state,
  query
FROM pg_stat_activity;

Это показывает, кто подключён и что делает.

Полезно для debugging.

Возможно, приложение имеет слишком много подключений.

Возможно, query зависла.

Возможно, кто-то открыл psql и ушёл обедать.

PostgreSQL знает.

PostgreSQL помнит.

PostgreSQL молча судит.

Находим медленные queries

PostgreSQL может логировать медленные queries, если это настроено.

Распространённая настройка:

log_min_duration_statement

Пример идеи:

логировать queries медленнее 1000 ms

Обычно это настраивается в PostgreSQL configuration files.

Для начинающих важная идея такая:

Медленные queries нужно наблюдать, а не угадывать.

Используй инструменты:

EXPLAIN ANALYZE
logs
monitoring
pg_stat_statements

pg_stat_statements — это extension, который помогает отслеживать query performance.

Это уже более advanced.

Но хорошо знать, что оно существует.

Работа с performance без наблюдения — это database astrology.

А database astrology мы уже не доверяем.

Backup and maintenance checklist

Простой checklist:

Создавай регулярные backup-и.
Храни backup-и вне database server.
Защищай backup-файлы.
Тестируй restore.
Делай backup перед migrations.
Используй app-specific users.
Держи PostgreSQL обновлённым.
Мониторь disk space.
Смотри slow queries.
Позволь autovacuum работать.
Запускай ANALYZE после больших imports, если нужно.
Документируй restore steps.

Documentation важна.

Процедура restore не должна жить только в твоей голове.

Особенно если твоя голова устала.

Или в отпуске.

Или пьёт кофе, пока production горит.

Запиши шаги.

Будущий ты заслуживает милости.

Типичные ошибки с backup-ами

Никогда не тестировать restore

Это самая большая ошибка.

Backup-файла недостаточно.

Нужно знать, что он восстанавливается.

Тестируй restore на другой базе.

Пример:

createdb -U postgres restore_test_db
pg_restore -U postgres -d restore_test_db shop_db_2026-05-03.dump

Потом проверь данные.

Доверяй, но проверяй.

А точнее, с backup-ами:

Не доверяй.
Проверяй.

Держать backup-и только на том же сервере

Если сервер умрёт, можно потерять базу и backup вместе.

Плохо.

Храни копии где-то ещё.

Backup должен пережить поломку оригинальной машины.

В этом весь смысл.

Делать backup-и слишком редко

Если делать backup раз в месяц, можно потерять месяц данных.

Возможно, это приемлемо для игрушечного проекта.

Не приемлемо для реального магазина.

Выбирай частоту backup-ов в зависимости от того, сколько данных можно позволить себе потерять.

У этого вопроса есть серьёзное название:

Recovery Point Objective

Простая версия:

Какая потеря данных приемлема?

Если ответ “почти никакая”, нужна серьёзная стратегия.

Не знать, сколько длится restore

Backup может существовать.

Но restore может занимать время.

Для маленьких баз — возможно, секунды.

Для огромных баз — возможно, часы.

Если приложение недоступно, время restore важно.

У этого вопроса есть ещё одно серьёзное название:

Recovery Time Objective

Простая версия:

Как долго система может быть offline?

Тут business people вдруг очень интересуются базами данных.

Интересно, как это работает.

Делать backup не той базы данных

Классическая ошибка.

Ты думаешь, что сделал backup production.

А на самом деле сделал backup local development.

Backup содержит трёх test users и продукт с названием “banana”.

Проверь:

SELECT current_database();

Проверь названия backup-файлов.

Проверь результат restore.

Не предполагай.

Практика

Создай backup backup_demo_db:

pg_dump -U postgres -d backup_demo_db > backup_demo_db.sql

Создай restore database:

createdb -U postgres backup_demo_restore_db

Восстанови:

psql -U postgres -d backup_demo_restore_db < backup_demo_db.sql

Проверь:

psql -U postgres -d backup_demo_restore_db
SELECT * FROM notes;

Создай custom backup:

pg_dump -U postgres -F c -d backup_demo_db -f backup_demo_db.dump

Создай ещё одну restore database:

createdb -U postgres backup_demo_custom_restore_db

Восстанови:

pg_restore -U postgres -d backup_demo_custom_restore_db backup_demo_db.dump

Проверь:

psql -U postgres -d backup_demo_custom_restore_db
SELECT * FROM notes;

Запусти maintenance:

VACUUM ANALYZE;

Проверь размер базы данных:

SELECT pg_size_pretty(pg_database_size(current_database()));

Это практично.

Это не гламурно.

Это полезно.

Как хорошая отвёртка.

Снова.

Базы данных любят отвёртки.

Метафорически.

Мини-задание

Создай backup plan для маленькой blog database.

Представь:

database name: blog_app_db
данные меняются каждый день
blog маленький
потеря больше одного дня данных — это плохо
deploy происходит каждую неделю

Напиши простой backup plan:

Backup frequency:
Backup format:
Backup location:
Retention:
Restore test frequency:
Backup before migrations:
Who can access backups:

Пример ответа:

Backup frequency: daily
Backup format: custom format через pg_dump -F c
Backup location: external secure storage
Retention: хранить daily backups 7 дней и weekly backups 1 месяц
Restore test frequency: раз в месяц
Backup before migrations: всегда
Who can access backups: только administrator

Теперь создай backup command:

pg_dump -U postgres -F c -d blog_app_db -f blog_app_db_2026-05-03.dump

Создай restore test command:

createdb -U postgres blog_app_restore_test_db
pg_restore -U postgres -d blog_app_restore_test_db blog_app_db_2026-05-03.dump

Потом напиши check query:

SELECT COUNT(*) FROM posts;

Так ты начинаешь думать как человек, ответственный за данные.

Немного страшно.

Очень полезно.

Очень взросло.

Итог

Сегодня ты изучил:

Этот урок чрезвычайно важен.

Возможно, не блестящий.

Но важный.

Разработчик, который умеет создавать таблицы, полезен.

Разработчик, который умеет делать запросы, лучше.

Разработчик, который умеет защищать и восстанавливать данные, намного надёжнее.

Потому что реальные проекты — это не только строить.

Это ещё и выживать после ошибок.

И backup-и — один из лучших способов выжить.

Итог курса

Ты дошёл до конца этого курса PostgreSQL.

Ты изучил:

Это много.

Ты изучил не просто команды.

Ты научился думать о данных.

Это важно.

Потому что приложения приходят и уходят.

Framework-и меняются.

Frontend trends меняются каждые пятнадцать минут.

Но данные остаются важными.

PostgreSQL — серьёзный инструмент.

Теперь ты знаешь достаточно, чтобы начать использовать его серьёзно.

Осторожно.

Практично.

И с backup-ами.

Всегда с backup-ами.

Финальные слова

PostgreSQL не всегда будет лёгким.

Иногда он будет жаловаться.

Иногда он отклонит твой query.

Иногда он скажет:

syntax error at or near...

и ты будешь смотреть на одну запятую десять минут.

Это нормально.

Ты изучаешь реальный инструмент.

Мощный инструмент.

Инструмент, который используют в реальных приложениях, реальных компаниях, реальных API, реальных dashboard-ах и реальных системах, где данные имеют значение.

Продолжай практиковаться.

Создавай маленькие проекты.

Ломай вещи.

Восстанавливай их.

Пиши queries.

Используй EXPLAIN ANALYZE.

Делай backup-и.

Тестируй backup-и.

Уважай данные.

И помни:

Browsers forget.
Databases remember.
Backups forgive.

Очень PostgreSQL.

Очень практично.

Очень хорошо.