В 3 семестре вы изучили реляционную модель данных, правила нормализации отношений от 1NF до BCNF, основы SQL-запросов и построение первичных индексов. На этом этапе база данных рассматривалась преимущественно как совокупность таблиц (отношений) и связей между ними.
Однако в реальных промышленных информационных системах (банковских АБС, медицинских архивах PACS, логистических центрах, ERP) база данных представляет собой высокоорганизованный комплекс взаимосвязанных объектов, управляемых системным каталогом СУБД. Грамотное проектирование требует применения специализированных объектов, решающих задачи изоляции подсистем, разграничения доступа, кэширования ресурсоемких расчетов и потоковой генерации уникальных ключей.
Каждая промышленная реляционная СУБД (PostgreSQL, Oracle, Microsoft SQL Server) организует пространство хранения в виде строгой многоуровневой иерархии:
logistics, модуль security, модуль billing), предотвратить конфликты имен таблиц и тонко настраивать права доступа групп пользователей.search_path определяет приоритет схем при обращении к объекту без явного квалификатора (например, просто SELECT * FROM clients вместо SELECT * FROM billing.clients). Команда: SET search_path TO billing, public;
SEQUENCE (Последовательность) — это специализированный объект базы данных, предназначенный для генерации неповторяющейся числовой последовательности (чаще всего целочисленной: INTEGER или BIGINT).
MAX(id) + 1?Наивная попытка вычислить следующий идентификатор через SELECT MAX(id) + 1 FROM table приводит к двум катастрофическим проблемам:
MAX(id), что приведет к нарушению ограничения уникальности PRIMARY KEY.Объект SEQUENCE работает вне транзакционного контекста через атомарные счетчики в оперативной памяти (Shared Memory):
-- Создание независимой последовательности
CREATE SEQUENCE billing.receipt_seq
START WITH 100000
INCREMENT BY 1
MINVALUE 100000
MAXVALUE 999999999
CACHE 20;
-- Основные функции работы с последовательностью:
-- 1. nextval('receipt_seq') - атомарно инкрементирует и возвращает новое значение.
-- 2. currval('receipt_seq') - возвращает текущее значение в рамках ДАННОЙ пользовательской сессии.
-- 3. setval('receipt_seq', 500000) - устанавливает счетчик на заданное число.
nextval(), завершилась с ошибкой или была отменена (ROLLBACK), сгенерированное число не возвращается обратно в последовательность. В первичных ключах возникают допустимые пропуски (Gaps). Последовательности проектируются ради скорости и уникальности, а не непрерывности.
Представление (View) в SQL — это именованный сохраненный запрос. В современной инженерии баз данных существует два принципиально разных вида представлений:
| Параметр сравнения | Обычное представление (VIEW) | Материализованное представление (MATERIALIZED VIEW) |
|---|---|---|
| Принцип работы | Виртуальная таблица. Текст SQL-запроса подставляется оптимизатором в абстрактное синтаксическое дерево (AST) клиентского запроса. | Физическая таблица-снапшот. Результат запроса однократно вычисляется и физически записывается на диск в блоки данных. |
| Занимаемая память на диске | 0 байт (хранится только мета-описание запроса в системном каталоге pg_views). |
Полноценный объем данных (включая дисковое пространство под созданные индексы). |
| Свежесть данных | Мгновенная (всегда отражает состояние базовых таблиц на микросекунду выполнения). | Статичный снимок на момент выполнения команды REFRESH. Данные могут отставать от оперативной базы. |
| Возможность индексации | Невозможно создать индекс на сам VIEW. | Поддерживает создание любых индексов (B-Tree, Hash, BRIN, GIN) прямо по вычисленным столбцам! |
| Скорость выполнения | Зависит от сложности исходного запроса (JOIN, подзапросы, агрегаты). Медленно на больших объемах. | Экстремально высокая (O(log N)) при наличии индексов, так как данные уже предвычислены. |
| Целевое назначение | Маскирование персональных данных, изоляция столбцов для ролей, упрощение сложных бизнес-выборок. | Аналитические отчеты (OLAP), дашборды руководителей, агрегация миллионов транзакций за сутки/месяцы. |
-- 1. Создание материализованной витрины
CREATE MATERIALIZED VIEW billing.mv_monthly_debt_summary AS
SELECT
s.district_id,
date_trunc('month', a.accrual_date)::date AS billing_month,
count(DISTINCT s.subscriber_id) AS active_subscribers_count,
sum(a.amount) AS total_accrued_rub,
sum(coalesce(p.paid_amount, 0)) AS total_paid_rub,
sum(a.amount - coalesce(p.paid_amount, 0)) AS total_debt_rub
FROM billing.subscribers s
JOIN billing.accruals a ON s.subscriber_id = a.subscriber_id
LEFT JOIN (
SELECT accrual_id, sum(amount) AS paid_amount
FROM billing.payments
GROUP BY accrual_id
) p ON a.accrual_id = p.accrual_id
GROUP BY s.district_id, date_trunc('month', a.accrual_date);
-- 2. Создание обязательного УНИКАЛЬНОГО индекса для фонового обновления
CREATE UNIQUE INDEX idx_mv_debt_pk
ON billing.mv_monthly_debt_summary (district_id, billing_month);
-- 3. Регламентное обновление данных:
-- Обычное обновление (блокирует чтение витрины эксклюзивным замком):
-- REFRESH MATERIALIZED VIEW billing.mv_monthly_debt_summary;
-- Конкурентное фоновое обновление (клиенты продолжают читать старый снимок без задержек):
REFRESH MATERIALIZED VIEW CONCURRENTLY billing.mv_monthly_debt_summary;
Реляционная модель требует атомарности значений (1NF). Однако введение перечислимых и составных типов на уровне СУБД повышает надежность модели данных и предотвращает запись мусорных строковых значений:
-- Перечислимый тип для статусов логистических отправлений
CREATE TYPE logistics.parcel_status AS ENUM (
'REGISTERED',
'IN_TRANSIT',
'ARRIVED_AT_HUB',
'OUT_FOR_DELIVERY',
'DELIVERED',
'RETURNED'
);
-- Составной тип для географических координат
CREATE TYPE logistics.coordinates AS (
lat NUMERIC(9, 6),
lon NUMERIC(9, 6)
);
В современной промышленной разработке проектирование архитектуры СУБД осуществляется в специализированных CASE-пакетах (Computer-Aided Software Engineering):
CREATE ...) для развертывания на боевом сервере.ROLLBACK) счетчик SEQUENCE не возвращается назад? К каким последствиям это привело бы в высоконагруженной системе?MATERIALIZED VIEW вместо обычного VIEW? Назовите минимум 2 фактора.REFRESH MATERIALIZED VIEW CONCURRENTLY?