Логическая и физическая независимость данных

Теоретический конспект лекции по дисциплине «ОП.08 Основы проектирования баз данных» (§2.2 с.7 программы)

1. Проблема файловых систем и происхождение независимости данных

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

Кризис файлового подхода: если бизнесу требовалось добавить к записи телефонного номера код города (расширив поле на 3 байта), все программы организации, работавшие с этим файлом, переставали функционировать. Требовалась ручная перекомпиляция и переписывание десятков тысяч строк прикладного кода!

Выход из кризиса предложил комитет ANSI/X3/SPARC в 1975 году, разделив архитектуру СУБД на три строго изолированных уровня.

2. Трехуровневая архитектура ANSI/SPARC и трансформация запросов

Архитектура ANSI/SPARC гарантирует, что пользователь и прикладное ПО взаимодействуют не с байтами на накопителе, а с абстрактными логическими отношениями.

1. ВНЕШНИЙ УРОВЕНЬ (External Level) — Представления пользователей
Внешние схемы (External Views): интерфейс бухгалтера, интерфейс складского работника, API мобильного приложения. Каждое приложение видит только необходимое подмножество данных.
↑↓
Трансформация «Внешний ↔ Концептуальный»: ЛОГИЧЕСКАЯ НЕЗАВИСИМОСТЬ ДАННЫХ
(Реализуется через SQL VIEW, триггеры INSTEAD OF, виртуальные вычисляемые столбцы)
↑↓
2. КОНЦЕПТУАЛЬНЫЙ УРОВЕНЬ (Conceptual Level) — Логическая схема БД
Концептуальная схема (Conceptual Schema): все таблицы (сущности), их столбцы (атрибуты), первичные ключи (PK), внешние ключи (FK) и бизнес-ограничения целостности (CHECK, UNIQUE). Полная информационная модель предметной области без привязки к дискам.
↑↓
Трансформация «Концептуальный ↔ Внутренний»: ФИЗИЧЕСКАЯ НЕЗАВИСИМОСТЬ ДАННЫХ
(Реализуется через B-Tree/Hash индексы, секции Partitioning, Tablespaces, сжатие страниц)
↑↓
3. ВНУТРЕННИЙ УРОВЕНЬ (Internal Level) — Физическое хранение
Внутренняя схема (Internal / Physical Schema): распределение по файлам ОС, блоки и страницы (по 8 КБ в PostgreSQL), кластеризованные индексы, сжатие lz4/zstd, таблицы размещения страниц на HDD/SSD.

Как трансформируется SQL-запрос через уровни ANSI/SPARC:

  1. Внешний уровень: Бухгалтерская программа отправляет привычный запрос: SELECT client_name, inn FROM Clients WHERE client_id = 42;.
  2. Трансформация «Внешний → Концептуальный»: СУБД анализирует каталог и обнаруживает, что Clients — это представление (VIEW). Парсер раскрывает макроподстановку и переписывает запрос к реальным концептуальным таблицам Legal_Entities и Individuals через UNION ALL.
  3. Трансформация «Концептуальный → Внутренний»: Оптимизатор СУБД (Cost-Based Optimizer) строит план выполнения: анализирует наличие B-Tree индекса на первичном ключе client_id, проверяет кэш страниц в оперативной памяти (Shared Buffers) и генерирует команды дискового ввода-вывода (IO) для считывания конкретной 8-килобайтной страницы с накопителя NVMe.

3. Логическая независимость: защита от рефакторинга схемы

Логическая независимость данных — это способность модифицировать концептуальную схему базы данных без необходимости изменять внешние схемы и прикладные программы, работающие с этими данными.

Когда бизнес растет, структура сущностей меняется: таблицы разбиваются на части (вертикальная или горизонтальная декомпозиция), объединяются, добавляются новые обязательные атрибуты.

Инженерный пример: Декомпозиция таблицы клиентов

Исходная ситуация: Существовала единая таблица Clients(client_id, name, inn, passport, kpp, address). С ней работает старая монолитная бухгалтерская программа, исходные коды которой утеряны или изменение которых стоит слишком дорого.

Потребность рефакторинга: Для соблюдения 3-й нормальной формы и исключения аномалий решено разделить ее на две специализированные таблицы:

Решение с помощью VIEW (сохранение логической независимости):

-- 1. Новая концептуальная схема:
CREATE TABLE Legal_Entities (
    client_id SERIAL PRIMARY KEY,
    company_name VARCHAR(255) NOT NULL,
    inn VARCHAR(12) NOT NULL,
    kpp VARCHAR(9) NOT NULL,
    address TEXT NOT NULL
);

CREATE TABLE Individuals (
    client_id SERIAL PRIMARY KEY,
    full_name VARCHAR(255) NOT NULL,
    inn VARCHAR(12),
    passport_data VARCHAR(50) NOT NULL,
    address TEXT NOT NULL
);

-- 2. Экранирующее представление для старой бухгалтерской программы:
CREATE OR REPLACE VIEW Clients AS
SELECT client_id, company_name AS name, inn, NULL AS passport, kpp, address, 'LEGAL' AS client_type
FROM Legal_Entities
UNION ALL
SELECT client_id, full_name AS name, inn, passport_data AS passport, NULL AS kpp, address, 'INDIVIDUAL' AS client_type
FROM Individuals;

-- 3. Обеспечение операций модификации через триггер INSTEAD OF:
CREATE OR REPLACE FUNCTION process_clients_insert()
RETURNS TRIGGER AS $$
BEGIN
    IF NEW.kpp IS NOT NULL THEN
        INSERT INTO Legal_Entities (client_id, company_name, inn, kpp, address)
        VALUES (NEW.client_id, NEW.name, NEW.inn, NEW.kpp, NEW.address);
    ELSE
        INSERT INTO Individuals (client_id, full_name, inn, passport_data, address)
        VALUES (NEW.client_id, NEW.name, NEW.inn, COALESCE(NEW.passport, 'N/A'), NEW.address);
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trg_clients_insert
INSTEAD OF INSERT ON Clients
FOR EACH ROW EXECUTE FUNCTION process_clients_insert();
Результат: Старая бухгалтерская программа продолжает отправлять привычные запросы к псевдотаблице Clients. Ни одна строчка клиентского программного кода не была переписана. Логическая независимость данных достигнута!

4. Физическая независимость: свобода управления инфраструктурой

Физическая независимость данных — это способность изменять физическую организацию данных (структуры хранения, методы доступа, размещение по дисковым томам, индексы), не внося никаких изменений в концептуальную схему и не меняя SQL-запросы в коде приложений.

Инженерный пример: Ускорение поиска с помощью B-Tree индекса

В интернет-магазине таблица Orders насчитывает 10 000 000 строк. Микросервис чекаута выполняет поиск по идентификатору пользователя:

SELECT order_id, order_date, total_sum 
FROM Orders 
WHERE user_id = 582103;

Ситуация до оптимизации: Индекс отсутствует. СУБД выполняет Sequential Scan (полное последовательное сканирование диска). Запрос читает 800 МБ страниц и выполняется 3.8 секунды. Сервер перегружен.

Действие администратора БД (DBA):

-- Создание B-Tree индекса на физическом уровне:
CREATE INDEX idx_orders_user_id ON Orders USING btree(user_id);

Ситуация после оптимизации: Запрос приложения не изменился ни на один символ. Однако оптимизатор PostgreSQL автоматически выбирает план Bitmap Index Scan / Index Scan. Время отклика падает с 3800 мс до 1.2 мс.

Другие ключевые механизмы физической независимости:

Инструмент СУБД Физическое действие Поведение прикладного SQL
Секционирование (Partitioning) Таблица разбивается на диске на секции по годам (orders_2024, orders_2025). Приложение шлет FROM Orders WHERE order_date >= .... СУБД сама считывает только нужный файл (Partition Pruning).
Табличные пространства (Tablespaces) Архивные таблицы переносятся с дорогого SSD NVMe на дешевый медленный HDD-массив RAID-6. Запросы чтения архива работают идентично; схема таблиц и имена колонок остаются прежними.
Сжатие данных (Compression) Включение алгоритма LZ4 для дисковых блоков таблицы. Приложение не знает о сжатии; распаковка выполняется ядром СУБД прозрачно в оперативной памяти.

5. Сравнительный анализ: Логическая vs Физическая независимость

Характеристика Логическая независимость Физическая независимость
Граница уровней ANSI/SPARC Между Внешним и Концептуальным Между Концептуальным и Внутренним
Что подвергается изменению? Концептуальная схема (разбиение таблиц, добавление атрибутов, нормализация) Физическая схема (индексы, таблицы размещения, дисковые массивы, секционирование)
Что защищается от правок? Внешние приложения, отчеты, старые сервисы, клиентские формы Концептуальная схема и SQL-запросы приложений
Основные инструменты реализации Представления (VIEW), материализованные представления, триггеры INSTEAD OF Индексы (B-Tree/Hash/GiST), секционирование (PARTITION BY), Tablespaces, сжатие
Сложность достижения на практике Высокая (требует глубокого анализа бизнес-логики и эквивалентности данных) Средняя / Низкая (автоматизирована ядром СУБД и оптимизатором запросов)

6. Вопросы для фундаментальной самопроверки

1. В чем главное отличие роли представления (VIEW) от создания B-Tree индекса?
Ответ: Представление (VIEW) обеспечивает логическую независимость, выступая виртуальным экраном между концептуальной схемой и внешним приложением при изменении состава таблиц. Индекс B-Tree обеспечивает физическую независимость, ускоряя дисковый доступ без изменения структуры таблиц и без модификации SQL-кода запроса.
2. Почему при разбиении таблицы для обеспечения логической независимости недостаточно одного лишь SELECT VIEW?
Ответ: Простое представление на основе UNION ALL доступно только для чтения. Чтобы сохранить возможность выполнять операции INSERT, UPDATE и DELETE со стороны старых систем, СУБД требует создания триггеров INSTEAD OF, которые берут на себя логику распределения данных по новым таблицам.
3. Изменится ли SQL-запрос мобильного приложения при переносе архивной таблицы на другой физический диск с помощью Tablespace?
Ответ: Нет. Благодаря физической независимости данных, перемещение файлов по точкам монтирования ОС является внутренней задачей администратора БД. Логическое имя таблицы и схема остаются прежними, поэтому клиенты продолжают отправлять те же самые запросы.
4. В каких случаях логическая независимость данных не может быть сохранена?
Ответ: Логическая независимость нарушается («закон сохранения информации»), если в ходе рефакторинга бизнес-атрибут был полностью удален из базы данных и не может быть вычислен или восстановлен из других атрибутов, в то время как внешнее приложение критически зависит от его значения.