Раздел 3 / 5

Информационное обеспечение систем автоматизации

Тема 3.1

Банки данных, СУБД, уровни представления

Назначение и компоненты систем баз данных — по методичке Дьякова «Базы данных: язык SQL».

Основные понятия

База данных (БД) — именованная совокупность структурированных данных, отражающая состояние объектов предметной области и их связей и организованная так, чтобы данные были независимы от прикладных программ.
СУБД — комплекс программных и языковых средств для создания, ведения и совместного использования баз данных. Банк данных = база данных + СУБД + технические средства + администратор + словарь данных.

БД — это библиотека: сами книги, расставленные по строгой системе. СУБД — библиотекарь: принимает запросы, знает, где что стоит, не пускает посторонних в хранилище и следит, чтобы две «правки» одной книги не столкнулись. Банк данных — вся библиотека как учреждение: фонд + библиотекарь + здание + каталог + директор (администратор).

Главная идея: приложения никогда не лезут в файлы напрямую — только через СУБД. Поэтому можно менять способ хранения, не переписывая программы.

Функции СУБД: определение данных (DDL), манипулирование данными (DML), управление транзакциями и параллельным доступом, восстановление после сбоев (журнализация), контроль целостности, разграничение доступа, оптимизация запросов, ведение словаря данных.

Обзор современных СУБД: реляционные — PostgreSQL, MySQL, Oracle Database, Microsoft SQL Server, SQLite, встраиваемые (Interbase/Firebird — на них построен практикум ТГТУ); нереляционные (NoSQL) — документные (MongoDB), «ключ–значение» (Redis), графовые (Neo4j).

За пределами реляционной модели (NoSQL) — для задач, где жёсткая схема и джойны мешают масштабированию: документные (MongoDB — JSON-документы), ключ-значение (Redis — кэш в памяти), колоночные (ClickHouse — аналитика), графовые (Neo4j — связи как первичная сущность). Плата за горизонтальное масштабирование — ослабленные гарантии согласованности (BASE вместо ACID). Для профиля «анализ данных» уместно сказать: рабочие данные — в реляционной СУБД, аналитические витрины — в колоночных.

Компоненты банка данных подробнее:

  • словарь данных (каталог) — «база данных о базе данных»: описания таблиц, атрибутов, типов, ограничений, индексов, представлений, пользователей и привилегий. Хранится в самой СУБД как системные таблицы (в SQL-стандарте — INFORMATION_SCHEMA), поэтому запросом можно узнать структуру любой таблицы;
  • администратор БД (АБД) — специалист (или группа), отвечающий за проектирование схемы, разграничение доступа, настройку производительности (индексы, планы запросов), резервное копирование и восстановление, мониторинг;
  • технические средства — серверы, дисковые массивы, сеть; организационно-методические средства — регламенты доступа, инструкции, документация.

Словарь данных — это тоже таблицы. Структуру любой таблицы можно узнать обычным запросом к системному каталогу:

SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_name = 'student';

СУБД ответит списком столбцов таблицы student с типами — «база данных о базе данных» доступна тем же языком SQL, что и сами данные. На этом строятся администраторские утилиты и ORM-генераторы.

Независимость данных — ключевое отличие подхода БД от файловых систем: описание данных (схема) хранится вместе с данными и отделено от прикладных программ. В файловых системах каждая программа «знала» формат своих файлов, и любое изменение формата требовало правки всех программ; дублирование одних данных в файлах разных отделов вело к противоречиям.

Классификация СУБД:

  • по модели данных — иерархические, сетевые, реляционные, объектно-реляционные, NoSQL;
  • по архитектуре — файл-серверные (данные — файл на общем диске, обработка на клиенте: Access, dBase; узкое место — сеть и блокировки), клиент-серверные (запросы выполняет сервер СУБД, клиенту уходит только результат: PostgreSQL, Oracle, MS SQL Server, Interbase/Firebird), встраиваемые (библиотека внутри приложения, без отдельного сервера: SQLite);
  • по размещению — централизованные и распределённые (данные на нескольких узлах, для приложения выглядят единой БД; нужны фрагментация, репликация и распределённые транзакции).

Файл-сервер против клиент-сервера на одном запросе «средний балл группы из 10 000 ведомостей»:

  • файл-серверная СУБД перекачает по сети все 10 000 записей на рабочую станцию и посчитает среднее там;
  • клиент-серверная выполнит SELECT AVG(...) на сервере и пришлёт по сети одно число.

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

Уровни представления. Схема и подсхема

Трёхуровневая архитектура ANSI/SPARC обеспечивает независимость данных:

  • внешний уровень — представления отдельных пользователей и приложений (подсхемы);
  • концептуальный уровень — обобщённая логическая модель всей предметной области (схема БД);
  • внутренний (физический) уровень — организация хранения: файлы, индексы, кластеры.
Схема — описание логической структуры всей БД (отношения, атрибуты, типы, ограничения); подсхема — описание части БД, видимой конкретному приложению или пользователю (в SQL — представления, view). Логическая независимость: изменение схемы не ломает подсхемы; физическая независимость: смена способа хранения не затрагивает схему.

Университетская БД на трёх уровнях:

  • внешний: деканат видит только «студент – группа – успеваемость», бухгалтерия — только «студент – стипендия»; ни те ни другие не знают о существовании чужих полей;
  • концептуальный: полная схема — таблицы СТУДЕНТ, ГРУППА, ВЕДОМОСТЬ, ПРИКАЗ со всеми связями;
  • внутренний: файлы данных, B-деревья индексов, страницы по 8 КБ на диске.

Добавили таблицу для военкомата — представления деканата не изменились (логическая независимость). Перенесли файлы на SSD и перестроили индекс — не изменилась даже схема (физическая независимость).

Как уровни связаны. Между соседними уровнями СУБД хранит отображения (mappings): внешне-концептуальное («поле „группа“ представления деканата — это атрибут name таблицы sgroup») и концептуально-внутреннее («таблица student лежит в файле X, проиндексирована B-деревом по id»). Запрос пользователя формулируется в терминах его подсхемы, СУБД по отображениям переводит его к концептуальной схеме, затем к физическим операциям чтения блоков. Именно наличие двух отображений и даёт две независимости: меняется уровень — переписывается только отображение, а не соседние уровни.

На собеседовании различайте пары терминов: схема (описание структуры, меняется редко) и состояние БД (данные в конкретный момент, меняются постоянно); логическая независимость (приложения ↔ схема) и физическая (схема ↔ хранение). Физическую независимость обеспечивают практически все СУБД, логическую — лишь частично: удаление используемого приложением атрибута всё равно его сломает.

демоТри уровня ANSI/SPARC: что ломается при изменениях

Вопросы к собеседованию

Что такое база данных, СУБД и банк данных?

БД — именованная совокупность структурированных данных предметной области, независимая от прикладных программ. СУБД — программные и языковые средства создания, ведения и совместного использования БД. Банк данных — система в целом: БД + СУБД + технические и организационно-методические средства + администратор.

Перечислите основные функции СУБД.

Определение данных (DDL), манипулирование (DML — поиск, вставка, обновление, удаление), управление транзакциями и параллельным доступом, журнализация и восстановление, контроль целостности, разграничение доступа, оптимизация запросов, словарь данных.

Опишите три уровня представления баз данных. Что такое схема и подсхема?

Внешний уровень — представления пользователей (подсхемы); концептуальный — логическая модель всей предметной области (схема); внутренний — физическое хранение (файлы, индексы). Архитектура даёт логическую (изменение схемы не затрагивает приложения) и физическую (смена хранения не затрагивает схему) независимость данных.

Тема 3.2

Модели данных

Иерархическая, сетевая и реляционная модели; отношение, ключи.

Три классические модели

  • Иерархическая — данные в виде дерева «предок–потомок»; у записи один родитель. Быстрая навигация вдоль иерархии, но связи «многие-ко-многим» требуют дублирования (IMS).
  • Сетевая — граф: запись может иметь много владельцев (модель CODASYL). Гибче иерархической, но сложна в сопровождении, доступ навигационный.
  • Реляционная (Э. Кодд, 1970) — данные в виде отношений (таблиц); доступ декларативный: указывается, что найти, а не как. Господствующая модель.
Модель данных — совокупность трёх составляющих: структур данных (из чего строится БД — записи и деревья, таблицы…), допустимых операций над ними (навигация по ссылкам либо операции реляционной алгебры) и ограничений целостности (какие состояния данных считаются корректными). Сравнивать модели нужно по всем трём пунктам, а не только по «форме хранения».

Одна и та же связь «студент учится в группе» в трёх моделях:

  • иерархическая: запись СТУДЕНТ физически подчинена записи ГРУППА; чтобы найти студента по фамилии, нужно обойти дерево от корня — путь доступа «зашит» в структуру;
  • сетевая: между ГРУППА и СТУДЕНТ объявлен групповой набор (set) «владелец–член»; программа навигационно движется по указателям: «найти владельца», «следующий член набора»;
  • реляционная: две таблицы и внешний ключ группа_id; связь — это совпадение значений, а не физический указатель, поэтому любой запрос формулируется декларативно и не зависит от путей доступа.

Почему победила реляционная модель: строгая математическая основа (теория множеств и логика предикатов — можно доказывать свойства запросов и преобразовывать их); физическая независимость данных (связи через значения, а не указатели, — СУБД свободна менять хранение); декларативный язык, доступный не только программистам; теория нормализации как формальная методика проектирования. Недостатки иерархической и сетевой моделей — навигационный доступ, жёсткие пути, перестройка структуры при изменении запросов — стали главным аргументом Кодда.

Современные ветви: объектно-ориентированная модель хранит объекты с методами и наследованием (ООСУБД остались нишевыми); объектно-реляционная — реляционная ядро + пользовательские типы, массивы, JSON (PostgreSQL); NoSQL-семейства (документные, ключ-значение, колоночные, графовые) жертвуют универсальностью запросов и строгой согласованностью ради масштабирования.

Иерархическая (дерево) Сетевая (граф) Факультет Кафедра А Кафедра Б Группа у записи один «родитель» Поставщик 1 Деталь 2 Поставка 1 Поставка 2 у записи много «владельцев»: M:N без дублирования
Дерево против графа: иерархическая модель дублирует данные при связях M:N, сетевая — нет, но её обработка навигационная.

Дублирование при M:N в иерархии — на числах. 3 поставщика поставляют по 4 детали, каждая деталь — у всех трёх поставщиков.

  • иерархическая модель (корень — ПОСТАВЩИК): каждая деталь повторяется под каждым своим поставщиком — 3·4 = 12 записей о деталях вместо 4; смена веса детали — правка в трёх местах;
  • сетевая: 3 записи поставщиков + 4 записи деталей + 12 записей-связок «поставка» с указателями — данные о детали хранятся один раз;
  • реляционная: то же самое таблицами — ПОСТАВЩИК (3 строки), ДЕТАЛЬ (4 строки), ПОСТАВКА(поставщик_id, деталь_id) (12 строк) — но связь через значения ключей, а не физические указатели.

Сетевая и реляционная модели устраняют дублирование одинаково — «таблицей-связкой»; разница в способе доступа: навигация по указателям против декларативного запроса.

Реляционная модель: термины

Отношение — множество кортежей одинаковой структуры (таблица). Схема отношения — имя отношения и набор атрибутов с доменами: R(A₁, A₂, …, An). Кортеж — строка, атрибут — столбец, домен — множество допустимых значений атрибута, степень — число атрибутов, мощность — число кортежей.

Свойства отношений: нет одинаковых кортежей; порядок кортежей и атрибутов не важен; значения атрибутов атомарны (нормализованность).

Ключи: потенциальный ключ — минимальный набор атрибутов, однозначно определяющий кортеж (уникальность + неизбыточность); один из потенциальных выбирается первичным (PRIMARY KEY, не допускает NULL); внешний ключ (FOREIGN KEY) — атрибут, ссылающийся на первичный ключ другого отношения — механизм связи таблиц и ссылочной целостности.

СТУДЕНТ(№ зачётки, паспорт, ФИО, группа). Потенциальных ключей два: {№ зачётки} и {паспорт} — каждый уникален и минимален. {№ зачётки, ФИО} ключом не является: уникален, но избыточен (номера зачётки уже достаточно). Первичным разумно выбрать № зачётки; паспорт останется альтернативным ключом (в SQL — UNIQUE). Часто вместо «природных» ключей вводят суррогатный — бессмысленный автоинкрементный id: он короток, никогда не меняется и не раскрывает персональных данных.

NULL и трёхзначная логика. NULL — отметка «значение отсутствует / неизвестно», а не ноль и не пустая строка. Любое сравнение с NULL даёт третье логическое значение UNKNOWN: условие оценка = 5 для строки с NULL не истинно и не ложно — строка просто не попадает в выборку. Проверка только через IS NULL / IS NOT NULL; NULL = NULL тоже даёт UNKNOWN. Агрегаты (кроме COUNT(*)) NULL игнорируют. Отсюда классическая ловушка: x = NULL в WHERE никогда не сработает.
демоNULL и трёхзначная логика: какие строки выберет WHERE

Требования Кодда (выборочно, «на понимание»): вся информация представлена только значениями в таблицах (информационное правило); каждый элемент данных адресуется именем таблицы, значением первичного ключа и именем столбца; системный каталог сам является реляционной БД; поддержка операций над множествами строк, а не только «запись за записью»; независимость данных от физического хранения. Эти правила — критерий «настоящей реляционности» СУБД.

Вопросы к собеседованию

Сравните иерархическую, сетевую и реляционную модели данных.

Иерархическая — дерево, у записи один предок: быстрый доступ вдоль иерархии, но «многие-ко-многим» требует дублирования. Сетевая — граф с многими владельцами записи: гибче, но сложная навигационная обработка. Реляционная — таблицы-отношения с декларативным доступом (SQL), строгая математическая основа; вытеснила первые две.

Что такое схема отношения, кортеж, атрибут, домен?

Схема отношения — имя и перечень атрибутов с доменами R(A₁…An). Кортеж — строка (набор значений атрибутов), атрибут — именованный столбец, домен — множество допустимых значений атрибута. Степень — число атрибутов, мощность — число кортежей.

Что такое потенциальный, первичный и внешний ключи?

Потенциальный ключ — минимальный набор атрибутов, уникально определяющий кортеж; их может быть несколько. Первичный — выбранный из потенциальных, не допускает NULL. Внешний — атрибут(ы), ссылающийся на первичный ключ другого отношения; обеспечивает связи и ссылочную целостность (нельзя сослаться на несуществующую запись).

Назовите свойства отношения в реляционной модели.

Отсутствие одинаковых кортежей (отношение — множество); порядок кортежей и порядок атрибутов несущественны; атомарность значений (в клетке — одно неделимое значение — первая нормальная форма).

Тема 3.3

Реляционная алгебра

Стандартные и специальные операции над отношениями.

Стандартные (теоретико-множественные) операции — над совместимыми отношениями: объединение (все кортежи обоих), пересечение, разность (кортежи первого, отсутствующие во втором), декартово произведение (все сочетания кортежей). Специальные: выборка σ (строки по условию), проекция π (заданные столбцы без дубликатов), соединение ⋈ (произведение + условие равенства атрибутов — естественное соединение), деление.

Совместимость по объединению — требование к операндам ∪, ∩ и −: одинаковая степень (число атрибутов) и попарно совпадающие домены атрибутов. Складывать «студентов» с «оценками» нельзя; «студентов дневного» со «студентами заочного» — можно. Для декартова произведения требование другое: у операндов не должно быть одноимённых атрибутов (иначе их переименовывают операцией ρ).

Теоретико-множественные операции на мини-таблицах. ДНЕВНОЕ = {Иванов, Петров}, ЗАОЧНОЕ = {Петров, Сидоров} (отношения с одним атрибутом «студент» — совместимы):

ДНЕВНОЕ ∪ ЗАОЧНОЕ = {Иванов, Петров, Сидоров} дубликат Петров — один раз ДНЕВНОЕ ∩ ЗАОЧНОЕ = {Петров} учится там и там ДНЕВНОЕ − ЗАОЧНОЕ = {Иванов} только дневное; операция несимметрична! ЗАОЧНОЕ − ДНЕВНОЕ = {Сидоров}

Пересечение выражается через разность: A ∩ B = A − (A − B) — поэтому базовыми считают пять операций (∪, −, ×, σ, π), остальные выводимы. Произведение: ГРУППА{ИВТ, ПИ} × ПРЕДМЕТ{БД, ИИ} = 2·2 = 4 кортежа (ИВТ-БД, ИВТ-ИИ, ПИ-БД, ПИ-ИИ) — мощности перемножаются, отсюда и название.

Виды соединений. Общий случай — θ-соединение: σθ(A × B), где θ — любое условие сравнения атрибутов (<, >, ≠ …). Если θ — равенство, соединение называется эквисоединением (в результате оба сравниваемых столбца). Естественное соединение — эквисоединение по всем одноимённым атрибутам с удалением дубликата столбца. Внешние соединения (left/right/full) добавляют непарные кортежи, дополняя их NULL, — расширение классической алгебры, вошедшее в SQL.

ОперацияОбозначениеSQL-эквивалент
ОбъединениеA ∪ BSELECT … UNION SELECT …
ПересечениеA ∩ BINTERSECT
РазностьA − BEXCEPT (MINUS)
ПроизведениеA × BFROM A, B (CROSS JOIN)
Выборкаσусловие(A)WHERE условие
Проекцияπатрибуты(A)SELECT DISTINCT атрибуты
СоединениеA ⋈ BJOIN … ON/USING
ДелениеA ÷ Bдвойное NOT EXISTS

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

демоОперации на живых таблицах

Реляционная алгебра на бумаге. СТУДЕНТ(id, имя, группа): {(1, Иванов, ИВТ), (2, Петров, ПИ), (3, Сидоров, ИВТ)}.

σгруппа='ИВТ'(СТУДЕНТ) = {(1, Иванов, ИВТ), (3, Сидоров, ИВТ)} строки по условию πгруппа(СТУДЕНТ) = {(ИВТ), (ПИ)} столбец, дубликат ИВТ исчез

Комбинация операций — уже запрос: «имена студентов ИВТ» = πимя(σгруппа='ИВТ'(СТУДЕНТ)) — ровно то, что делает SELECT имя FROM СТУДЕНТ WHERE группа='ИВТ'.

Деление — самая хитрая операция: СДАЛ(студент, предмет) ÷ ПРЕДМЕТ(предмет) = студенты, сдавшие все предметы из второго отношения. Если СДАЛ = {(Иванов, БД), (Иванов, ИИ), (Петров, БД)} и ПРЕДМЕТ = {(БД), (ИИ)}, то результат — {Иванов}: только у него есть пара с каждым предметом делителя. В SQL деление выражается через двойное NOT EXISTS — потому его и спрашивают «на понимание».

Вопросы к собеседованию

Перечислите операции реляционной алгебры.

Стандартные (теоретико-множественные): объединение, пересечение, разность, декартово произведение. Специальные: выборка σ (фильтр строк по условию), проекция π (выбор столбцов с удалением дубликатов), соединение ⋈ (декартово произведение + условие на атрибуты; частный случай — естественное по равенству одноимённых атрибутов), деление. SQL-запрос SELECT реализует комбинацию этих операций.

Чем выборка отличается от проекции?

Выборка σ работает по строкам: оставляет кортежи, удовлетворяющие условию (WHERE). Проекция π — по столбцам: оставляет указанные атрибуты и устраняет дубликаты кортежей (SELECT DISTINCT списка столбцов).

Что такое естественное соединение?

Соединение двух отношений по равенству всех одноимённых атрибутов, при котором повторяющийся атрибут в результат входит один раз. Общий случай — θ-соединение: декартово произведение с произвольным условием сравнения атрибутов. В SQL — JOIN … ON/USING.

Тема 3.4

Язык SQL

Язык манипулирования данными реляционной модели. Создание и модификация БД, поиск, сортировка, индексирование, формы и отчёты.

SQL — декларативный язык; группы операторов: DDL (CREATE, ALTER, DROP), DML (SELECT, INSERT, UPDATE, DELETE), DCL (GRANT, REVOKE), управление транзакциями (COMMIT, ROLLBACK). Бывает интерактивным и вложенным (встроенным в прикладную программу).

-- создание и модификация
CREATE TABLE student (
  id      INTEGER PRIMARY KEY,
  name    VARCHAR(60) NOT NULL,
  group_id INTEGER REFERENCES sgroup(id),
  rating  NUMERIC(4,2) DEFAULT 0
);
ALTER TABLE student ADD COLUMN email VARCHAR(80);
CREATE INDEX idx_student_group ON student(group_id);

-- манипулирование
INSERT INTO student(id, name, group_id) VALUES (1, 'Иванов', 3);
UPDATE student SET rating = 4.5 WHERE id = 1;
DELETE FROM student WHERE rating < 2;

-- поиск, сортировка, агрегаты
SELECT g.name, COUNT(*) AS n, AVG(s.rating) AS avg_r
FROM student s
JOIN sgroup g ON g.id = s.group_id
WHERE s.rating >= 3
GROUP BY g.name
HAVING COUNT(*) > 5
ORDER BY avg_r DESC;

Порядок логического выполнения SELECT: FROM → JOIN → WHERE → GROUP BY → HAVING → SELECT → ORDER BY. Индекс ускоряет поиск и сортировку по столбцу ценой замедления вставок и дополнительной памяти. Представление (CREATE VIEW) — сохранённый запрос-«виртуальная таблица» — механизм подсхем. Формы — экранный интерфейс ввода и просмотра записей; отчёты — форматированный вывод выборок для печати (строятся средствами конкретной СУБД — практикум ТГТУ использует Interbase/Delphi).

Типы данных SQL: числовые точные (INTEGER, SMALLINT, NUMERIC(p,s)/DECIMAL — для денег) и приближённые (REAL, DOUBLE PRECISION); строковые фиксированной (CHAR(n)) и переменной (VARCHAR(n)) длины; дата-время (DATE, TIME, TIMESTAMP); логический BOOLEAN; большие объекты (BLOB/CLOB). Выбор типа — тоже ограничение целостности: домен атрибута в SQL задаётся типом плюс CHECK.

Условия WHERE, о которых спрашивают: BETWEEN a AND b (включительно), IN (список), LIKE с шаблонами % (любая строка) и _ (один символ), IS NULL. Предикаты над подзапросами: EXISTS (подзапрос непуст), ANY/SOME (сравнение хотя бы с одним значением), ALL (со всеми): x > ALL(…) — «больше максимума», x > ANY(…) — «больше минимума». DISTINCT убирает дубликаты строк результата.

GRANT/REVOKE — разграничение доступа (DCL):

GRANT SELECT, INSERT ON student TO dekanat;
GRANT SELECT ON v_stipend TO buhgalteria;   -- доступ только к представлению
REVOKE INSERT ON student FROM dekanat;
GRANT SELECT ON student TO analyst WITH GRANT OPTION; -- может передавать право дальше

Типовая связка «представление + привилегия»: бухгалтерии выдаётся право не на таблицу, а на view с нужными столбцами — так подсхема и защита реализуются одним механизмом.

Серверная логика: хранимые процедуры — именованные программы на процедурном расширении SQL (PSQL в Interbase/Firebird, PL/pgSQL в PostgreSQL), выполняются на сервере — меньше сетевых обменов, единая бизнес-логика; триггеры — процедуры, автоматически срабатывающие BEFORE/AFTER INSERT/UPDATE/DELETE строки, — сложные правила целостности (журналирование изменений, каскадные пересчёты); генераторы/последовательности (SEQUENCE) — источник уникальных номеров для суррогатных ключей.

Частые уточняющие вопросы по SELECT: 1) чем WHERE отличается от HAVING (строки до группировки против групп после); 2) почему нельзя написать WHERE AVG(оценка) > 4 (агрегат ещё не вычислен); 3) что вернёт COUNT(*) против COUNT(столбец) (все строки против не-NULL значений); 4) зачем DISTINCT внутри агрегата: COUNT(DISTINCT группа) — число разных групп.

демоSELECT по шагам: что происходит с таблицей

LEFT JOIN против INNER JOIN — группы: ИВТ-41, ПИ-42 и новая пустая АСУ-43.

  • INNER JOIN групп со студентами вернёт строки только для ИВТ-41 и ПИ-42 — у АСУ-43 нет пары;
  • LEFT JOIN вернёт и АСУ-43 со значением NULL в столбцах студента — «все группы, даже пустые».

Подзапрос — тот же смысл другой записью: «студенты групп 3-го курса»:

SELECT name FROM student
WHERE group_id IN (SELECT id FROM sgroup WHERE course = 3);
демоЧетыре вида JOIN на живых таблицах

Агрегаты и HAVING на числах. Оценки: Иванов — 5, 4; Петров — 3; Сидоров — 5, 5, 4 (все из ИВТ, Петров из ПИ).

SELECT группа, COUNT(*) AS оценок, AVG(оценка) AS средний
FROM ведомость GROUP BY группа HAVING AVG(оценка) >= 4;
группаоценоксредний
ИВТ5(5+4+5+5+4)/5 = 4,6

Группа ПИ (средний 3) отсечена HAVING после агрегирования — WHERE так не смог бы: он работает до группировки и агрегатов ещё не знает. Частая ошибка на собеседовании — WHERE AVG(...) — как раз про это.

Коррелированный подзапрос — «студенты с оценкой выше средней по своей группе»:

SELECT s.name FROM student s
WHERE s.rating > (SELECT AVG(s2.rating) FROM student s2
                  WHERE s2.group_id = s.group_id);

Подзапрос выполняется для каждой строки внешнего запроса, ссылаясь на неё (s.group_id), — в отличие от независимого подзапроса, который вычисляется один раз.

Вопросы к собеседованию

Какие группы операторов входят в SQL?

DDL — определение данных (CREATE, ALTER, DROP); DML — манипулирование (SELECT, INSERT, UPDATE, DELETE); DCL — управление доступом (GRANT, REVOKE); TCL — транзакции (COMMIT, ROLLBACK, SAVEPOINT). SQL может быть интерактивным и вложенным в прикладную программу.

Опишите структуру оператора SELECT и порядок его выполнения.

SELECT списка выражений FROM таблиц [JOIN … ON] [WHERE условие] [GROUP BY группировка] [HAVING условие на группы] [ORDER BY сортировка]. Логический порядок: FROM/JOIN → WHERE (фильтр строк) → GROUP BY → HAVING (фильтр групп) → SELECT (проекция, агрегаты) → ORDER BY. WHERE отбирает строки до группировки, HAVING — группы после агрегирования.

Что такое индекс и когда его создают?

Дополнительная структура (обычно B-дерево), хранящая значения столбца со ссылками на записи, — ускоряет поиск, соединения и сортировку с O(n) до O(log n). Цена: память и замедление INSERT/UPDATE (индекс надо поддерживать). Создают по столбцам частых условий поиска и соединений; первичный ключ индексируется автоматически.

Что такое представление (VIEW), формы и отчёты?

Представление — именованный сохранённый запрос, ведущий себя как виртуальная таблица; реализует подсхемы и разграничение доступа. Формы — экранный интерфейс ввода/редактирования записей; отчёты — форматированный вывод данных для печати с группировками и итогами. Формы и отчёты строятся инструментами конкретной СУБД или средой разработки.

Чем JOIN отличается от вложенного подзапроса? Какие бывают соединения?

JOIN соединяет строки таблиц по условию: INNER — только совпавшие пары; LEFT/RIGHT OUTER — плюс непарные строки одной из сторон (с NULL); FULL — с обеих; CROSS — декартово произведение. Подзапрос возвращает значение или множество для условия (IN, EXISTS). Многие запросы записываются обоими способами; оптимизатор часто сводит их к одному плану.

Тема 3.5

Проектирование реляционной БД

Функциональные зависимости, декомпозиция, нормальные формы, метод «сущность–связь».

Функциональные зависимости и нормализация

Функциональная зависимость X → Y: каждому значению набора атрибутов X соответствует ровно одно значение Y. Полная ФЗ — Y зависит от всего составного ключа, а не от его части; транзитивная — X → Z через посредника: X → Y и Y → Z.

Функциональные зависимости в таблице ВЕДОМОСТЬ(студент, группа, куратор, предмет, оценка):

{студент, предмет} → оценка полная (нужен весь ключ) студент → группа от части ключа — нарушает 2НФ студент → группа → куратор транзитивная — нарушает 3НФ

Каждая «неправильная» зависимость — готовый рецепт декомпозиции: её левую часть делаем ключом новой таблицы (смотрите демо нормализации ниже).

Вывод зависимостей — аксиомы Армстронга. Из заданного множества ФЗ выводятся новые по трём правилам:

рефлексивность: если Y ⊆ X, то X → Y тривиальные ФЗ пополнение: X → Y ⇒ XZ → YZ транзитивность: X → Y, Y → Z ⇒ X → Z

Аксиомы корректны (выводят только истинные ФЗ) и полны (выводят все). Замыкание X⁺ — множество всех атрибутов, функционально зависящих от X; практический смысл: X — потенциальный ключ отношения ⇔ X⁺ содержит все атрибуты, а сам X неизбыточен. Так проверка «является ли набор ключом» сводится к механическому вычислению замыкания.

R(A, B, C, D) с ФЗ: A → B, B → C. Замыкание {A}⁺: стартуем с {A}; A → B даёт {A, B}; B → C даёт {A, B, C}; D недостижим ⇒ {A}⁺ = {A, B, C} ≠ {A, B, C, D} — A не ключ. Зато {A, D}⁺ = все атрибуты, и ни A, ни D по отдельности не хватает ⇒ {A, D} — потенциальный ключ.

демоЗамыкание атрибутов: ключ или не ключ?

Плохо спроектированное отношение страдает аномалиями: избыточность (дублирование данных), аномалии обновления, вставки и удаления. Лекарство — декомпозиция: разбиение отношения на проекции без потерь (соединение проекций восстанавливает исходное отношение — теорема Хита) и без потери ФЗ.

Вся нормализация — одно правило: каждый факт хранится ровно один раз. «Куратор группы ИВТ-41 — Дьяков» — это факт о группе, а не о каждом её студенте; значит, ему место в таблице групп, одной строкой. Тогда смена куратора — правка одной клетки, и рассогласование невозможно в принципе.

  • 1НФ — все значения атомарны, нет повторяющихся групп.
  • 2НФ — 1НФ + каждый неключевой атрибут полностью зависит от составного ключа (нет зависимостей от части ключа).
  • 3НФ — 2НФ + нет транзитивных зависимостей неключевых атрибутов от ключа.
  • НФБК — каждый детерминант ФЗ является потенциальным ключом (усиление 3НФ).

Когда 3НФ мало: пример на НФБК. РАСПИСАНИЕ(студент, предмет, преподаватель): каждый преподаватель ведёт один предмет; у студента по каждому предмету один преподаватель. ФЗ: {студент, предмет} → преподаватель и преподаватель → предмет.

Отношение в 3НФ (неключевых транзитивных зависимостей нет), но детерминант «преподаватель» — не потенциальный ключ ⇒ НФБК нарушена: предмет преподавателя дублируется в каждой его строке, со всеми аномалиями. Декомпозиция: ПРЕПОД(преподаватель, предмет) + СЛУШАЕТ(студент, преподаватель).

Выше НФБК (называют, но подробно не разбирают): 4НФ устраняет многозначные зависимости X →→ Y — когда в одной таблице независимо перечислены два множества фактов об X (преподаватель ведёт {предметы} и владеет {языками}: хранение в одной таблице порождает декартово произведение строк); 5НФ — зависимости соединения (отношение восстановимо только соединением трёх и более проекций). На практике проектируют до 3НФ/НФБК.

Многозначная зависимость на числах (мотив 4НФ). Преподаватель Дьяков ведёт {БД, SQL} и владеет {Pascal, C++} — предметы и языки независимы. Хранение в одной таблице требует всех сочетаний, иначе появится ложный факт «БД связана с Pascal»:

преподавательпредметязык
ДьяковБДPascal
ДьяковБДC++
ДьяковSQLPascal
ДьяковSQLC++

2 предмета × 2 языка = 4 строки; добавился третий язык — вставлять придётся сразу две строки. Функциональных зависимостей здесь нет вовсе (ключ — все три атрибута), поэтому 3НФ и НФБК формально соблюдены. Лечит 4НФ: декомпозиция на ВЕДЁТ(преподаватель, предмет) и ВЛАДЕЕТ(преподаватель, язык) — 2 + 2 строки без сочетаний.

Денормализация — осознанный шаг назад: слияние таблиц или хранение вычисляемых итогов ради скорости чтения (меньше соединений). Цена — дублирование и риск рассогласования, поэтому применяется точечно: в отчётных витринах, хранилищах данных (схема «звезда»), кэш-полях с пересчётом триггером. Правило: сначала нормализовать, потом — при доказанной необходимости — денормализовать.

Этапы проектирования БД целиком: 1) системный анализ предметной области (какие объекты, процессы, документы, запросы); 2) инфологическое (концептуальное) проектирование — ER-модель, независимая от СУБД; 3) даталогическое — отображение в реляционную схему конкретной СУБД + нормализация; 4) физическое — индексы, файловые структуры, распределение по носителям. Ошибка на раннем этапе стоит дороже всего: перестройка схемы работающей БД тянет за собой данные, запросы и приложения.

демоНормализация на сквозном примере

Метод «сущность–связь» (ER)

Инфологическое проектирование: предметная область описывается сущностями (объекты с атрибутами), связями между ними (1:1, 1:M, M:N) и ключами. Затем — даталогическое проектирование: ER-диаграмма отображается в реляционную схему: сущность → таблица, атрибут → столбец, связь 1:M → внешний ключ на стороне «многих», связь M:N → отдельная таблица-связка из двух внешних ключей.

Словарь ER-модели: сущность — тип объектов (СТУДЕНТ), экземпляр — конкретный объект (Иванов); атрибуты бывают простые и составные (адрес = город + улица), однозначные и многозначные (телефоны — при переводе в схему уходят в отдельную таблицу), производные (возраст вычисляется из даты рождения — не хранят). У связи различают кардинальность (1:1, 1:M, M:N — «сколько максимум») и класс принадлежности / модальность (обязательная или необязательная — «может ли не быть»): студент обязан числиться в группе, группа может быть без куратора. Обязательность определяет NOT NULL у внешнего ключа.

Слабая сущность — сущность, не имеющая собственного полного ключа и существующая только вместе с владельцем: ОЦЕНКА существует лишь у конкретного студента по конкретному предмету. Её ключ составной: ключ владельца + частичный ключ (студент_id + предмет_id). Удаление владельца влечёт удаление слабых экземпляров (ON DELETE CASCADE).

Правила перевода ER → реляционная схема (проговорить списком):

  1. каждая сильная сущность → таблица; простые атрибуты → столбцы; ключ → PRIMARY KEY;
  2. составной атрибут разворачивается в отдельные столбцы; многозначный → отдельная таблица (id владельца + значение);
  3. связь 1:M → внешний ключ в таблице стороны «M»; при обязательной связи — NOT NULL;
  4. связь 1:1 → внешний ключ с UNIQUE в любой из таблиц (обычно на стороне с обязательным участием) либо слияние в одну таблицу;
  5. связь M:N → таблица-связка: два внешних ключа, вместе — составной первичный ключ; атрибуты связи (дата записи на курс) живут в связке;
  6. слабая сущность → таблица с составным ключом «ключ владельца + частичный ключ» и каскадным удалением.
демоER → реляционная схема: как превращается связь

ГРУППА id (PK) название СТУДЕНТ id (PK) имя группа_id (FK) КУРС id (PK) название 1 : M M : N СТУДЕНТ_КУРС студент_id + курс_id связь M:N реализуется таблицей-связкой из двух FK
ER-модель и её отображение в реляционную схему: 1:M — внешний ключ у «многих», M:N — таблица-связка.

Вопросы к собеседованию

Что такое функциональная, полная и транзитивная зависимости?

ФЗ X → Y: значению X соответствует ровно одно значение Y. Полная — Y зависит от всего составного ключа и не зависит от его части. Транзитивная — X → Z через посредника (X → Y, Y → Z, где Y не ключ). Полные и транзитивные зависимости — критерии 2НФ и 3НФ соответственно.

Какие аномалии возникают в ненормализованных отношениях?

Избыточность — многократное дублирование одних данных; аномалия обновления — при изменении факта нужно править много строк, рискуя рассогласованием; аномалия вставки — нельзя записать факт без «лишних» данных (например, преподавателя без группы); аномалия удаления — удаляя строку, теряем последнюю копию независимого факта.

Дайте определения 1НФ, 2НФ и 3НФ.

1НФ: значения атомарны, нет повторяющихся групп. 2НФ: 1НФ + каждый неключевой атрибут полностью функционально зависит от всего составного ключа. 3НФ: 2НФ + нет транзитивных зависимостей неключевых атрибутов от ключа (неключевые атрибуты не зависят друг от друга). НФБК: всякий детерминант — потенциальный ключ.

Что значит «декомпозиция без потерь»?

Разбиение отношения на проекции, естественное соединение которых в точности восстанавливает исходное отношение — ни потери, ни появления ложных кортежей. По теореме Хита декомпозиция R(X, Y, Z) на (X, Y) и (X, Z) без потерь, если X → Y или X → Z. Также стремятся сохранить все функциональные зависимости.

Опишите проектирование БД методом «сущность–связь».

Инфологический этап: выделяются сущности с атрибутами и ключами, связи типов 1:1, 1:M, M:N — строится ER-диаграмма, независимая от СУБД. Даталогический этап: сущность → таблица, атрибут → столбец, 1:M → внешний ключ у стороны «многих», M:N → таблица-связка из внешних ключей. Далее проверка нормальных форм и физическое проектирование (индексы).

Тема 3.6

Физическая организация, защита и целостность

Хешированные и индексированные файлы, защита БД, транзакции.

Физическая организация данных

  • Последовательные файлы — записи подряд; поиск O(n), вставка в конец.
  • Хешированные файлы — адрес записи вычисляется хеш-функцией от ключа h(K); поиск по ключу O(1). Проблема — коллизии (разным ключам — один адрес): разрешаются цепочками переполнения или открытой адресацией. Диапазонный поиск неэффективен.
  • Индексированные файлы — отдельная структура «значение ключа → адрес записи». Индекс может быть плотным (на каждую запись) и неплотным (на блок); первичным и вторичным. Основная структура — B-дерево/B⁺-дерево: сбалансированное многоветвистое дерево, все листья на одной глубине, поиск/вставка O(log n), листья B⁺-дерева связаны списком — быстрый диапазонный поиск.

Единица обмена с диском — страница (блок), обычно 4–16 Кбайт: СУБД никогда не читает «одну запись», только страницу целиком, а в оперативной памяти держит буферный пул недавно использованных страниц. Поэтому стоимость запроса меряют числом обращений к диску, и все физические структуры проектируются «страницами»: узел B-дерева = страница, корзина хеш-файла = страница.

Виды индексов подробнее:

  • плотный — статья индекса на каждую запись; разреженный (неплотный) — одна статья на страницу (её минимальный ключ), возможен только по упорядоченному файлу: находим нужную страницу по индексу, внутри — последовательно;
  • первичный — по ключу упорядочения файла (один на таблицу), вторичные — по прочим атрибутам (всегда плотные: файл по ним не упорядочен);
  • кластерный — сами записи физически уложены в порядке ключа индекса (в B⁺-дереве листья и есть данные), один на таблицу; некластерный — листья хранят ссылки на записи. Диапазонный запрос по кластерному индексу читает соседние страницы, по некластерному — прыгает по всему файлу;
  • составной — по нескольким столбцам (группа, имя): работает для условий по префиксу списка столбцов.

Хеширование подробнее. Хеш-функция должна равномерно рассеивать ключи; классика — деление с остатком h(K) = K mod M, где M — простое число корзин. При коэффициенте заполнения выше ~0,7–0,8 цепочки растут и поиск деградирует; статический хеш-файл приходится перестраивать целиком. Расширяемое (динамическое) хеширование решает это без полной перестройки: используется каталог указателей на корзины, при переполнении расщепляется лишь одна корзина, а каталог при необходимости удваивается — число дисковых обращений остаётся 1–2 при любом росте данных.

КритерийХеш-файлB⁺-дерево
Поиск по ключуO(1) — лучший выборO(log n), 3–4 чтения
Диапазон (BETWEEN), сортировканепригоден: порядок разрушенэффективен: листья-список
Рост данныхперестройка / расширяемое хешированиесаморасщепление узлов
Использование в СУБДхеш-индексы, хеш-соединенияиндекс «по умолчанию»
демоПоиск записи: полный перебор против индекса
Одна и та же таблица из 32 записей. Верхняя строка — поиск без индекса: читаем подряд, пока не наткнёмся. Нижняя — двоичный поиск по отсортированному индексу: прыжок в середину, отбрасываем половину, снова. На 32 записях это 5 сравнений против ~16; на миллионе — 20 против 500 000.
демоХеш-файл: раскладываем записи по корзинам
Адрес корзины = ключ mod 7. Запись падает сразу в свою корзину — поиск по ключу за одно обращение. Но когда два ключа дают один адрес (подсветка), возникает коллизия — запись уходит в цепочку переполнения, и поиск в этой корзине замедляется.
демоB-дерево: поиск и вставка с расщеплением
Ползунок подсвечивает путь поиска: любой ключ — за «высоту дерева» обращений. А кнопка вставки показывает, откуда берётся сбалансированность: добавляйте ключи, пока какой-нибудь лист не переполнится — он расщепится, медиана уйдёт вверх; переполнится корень — расщепится и он, и дерево подрастёт в высоту целиком, оставаясь идеально ровным. Именно поэтому B-дерево никогда не вырождается в список.
30 | 60 5 | 12 | 21 34 | 47 | 55 68 | 77 | 90 ключи < 30 · 30 ≤ ключи < 60 · ключи ≥ 60 все листья на одной глубине; в B⁺-дереве листья связаны списком для диапазонного поиска
B⁺-дерево — основа индексов реляционных СУБД.

Почему хватает 3–4 уровней. Узел B-дерева подгоняют под дисковый блок 8 Кбайт: помещается ~200 пар «ключ + ссылка».

1 уровень: 200 записей;  2 уровня: 200² = 40 000;  3 уровня: 200³ = 8·10⁶;  4 уровня: 1,6·10⁹

Таблица на миллиард строк — 4 чтения с диска до любой записи (а верхние уровни ещё и постоянно сидят в кэше — фактически 1–2 чтения). Двоичному дереву понадобилось бы log₂ 10⁹ ≈ 30 уровней-обращений: вся сила B-дерева — в «ширине» узла, согласованной с блоком диска.

Защита, целостность и сохранность БД

  • Защита: идентификация и аутентификация пользователей; привилегии GRANT/REVOKE на таблицы и операции; представления, скрывающие часть данных; шифрование; аудит.
  • Целостность — соответствие данных ограничениям предметной области: целостность сущностей (первичный ключ уникален и не NULL), ссылочная целостность (внешние ключи ссылаются на существующие записи; ON DELETE CASCADE/RESTRICT), ограничения CHECK, NOT NULL, UNIQUE, триггеры.
  • Сохранность — восстановление после сбоев: транзакции со свойствами ACID (атомарность, согласованность, изоляция, долговечность), журнал изменений (упреждающая запись), контрольные точки, резервное копирование.
демоТранзакция: перевод денег

Перевод 100 ₽ со счёта А на счёт Б — это два UPDATE. Если между ними выключат свет, без транзакций деньги «испарятся»: с А списано, на Б не зачислено. Транзакция делает пару операций неделимой: либо обе (COMMIT), либо ни одной (ROLLBACK — СУБД откатит по журналу). Попробуйте в демо нажать «сбой» в середине. А кнопка «второй клиент» показывает изоляцию: остановитесь между двумя UPDATE и прочитайте сумму на READ UNCOMMITTED — увидите несуществующие 700 ₽ (грязное чтение); на READ COMMITTED читатель видит только зафиксированные 800.

Изоляция параллельных транзакций. Без изоляции возникают аномалии: грязное чтение (видны незафиксированные чужие изменения), неповторяющееся чтение (два чтения одной строки дают разное — её успели изменить), фантомы (повторный запрос по условию возвращает новые строки). Стандарт SQL задаёт уровни изоляции — компромисс строгости и параллелизма:

УровеньГрязное чтениеНеповтор. чтениеФантомы
READ UNCOMMITTEDвозможновозможновозможно
READ COMMITTED—возможновозможно
REPEATABLE READ——возможно
SERIALIZABLE———

Реализация — блокировки (чтения/записи, строк/таблиц; риск взаимоблокировок) или многоверсионность MVCC: читатели видят «снимок» данных и не блокируют писателей.

Блокировки и взаимоблокировка (deadlock). Разделяемая S-блокировка (чтение) совместима с другими S, но не с исключительной X-блокировкой (запись); X не совместима ни с чем. Двухфазный протокол (2PL): транзакция сначала только набирает блокировки, потом только отпускает — это гарантирует сериализуемость.

T₁: заблокировала счёт А, ждёт Б;   T₂: заблокировала Б, ждёт А цикл ожидания — deadlock

СУБД обнаруживает цикл в графе ожидания и принудительно откатывает одну транзакцию («жертву»); приложение должно уметь повторить её. Профилактика — захватывать ресурсы во всех транзакциях в одном и том же порядке.

демоВзаимоблокировка двух транзакций по шагам

Как журнал спасает данные (WAL — упреждающая запись). Правило: сначала запись о изменении попадает в журнал на диске, и только потом меняются сами страницы данных. В журнале хранятся до-образ (старое значение) и после-образ (новое).

  1. Транзакция уменьшила счёт А на 100 ₽ → в журнал пишется «А: было 500, стало 400», затем COMMIT-отметка.
  2. 💥 Сбой питания до записи страницы данных на диск.
  3. Восстановление при старте: СУБД читает журнал. Транзакции с COMMIT-отметкой повторяются по после-образам (redo), незавершённые — откатываются по до-образам (undo).

Плюс периодические контрольные точки: все грязные страницы сбрасываются на диск, журнал усечается — восстановление начинается с последней контрольной точки, а не с начала времён. Резервные копии + журнал = восстановление на любой момент времени.

Модели разграничения доступа: дискреционная (избирательная) — у каждого объекта есть владелец, раздающий привилегии конкретным пользователям и ролям (GRANT/REVOKE; так работают все SQL-СУБД); мандатная — объектам присваиваются метки секретности, субъектам — уровни допуска, правила сравнения меток задаёт система, а не владелец (защищённые СУБД для гостайны); ролевая (RBAC) — привилегии собираются в роли («деканат», «бухгалтер»), пользователям выдаются роли — на практике дополняет дискреционную.

SQL-инъекция — главная прикладная угроза. Программа склеивает запрос из строки пользователя:

query = "SELECT * FROM users WHERE name = '" + name + "'";
-- пользователь ввёл:  ' OR '1'='1
SELECT * FROM users WHERE name = '' OR '1'='1';   -- вернёт всех

Защита: параметризованные запросы (значение передаётся отдельно от текста SQL и не интерпретируется), проверка входных данных, минимальные привилегии учётной записи приложения, хранимые процедуры.

Резервное копирование: полное — вся БД (долго, но восстановление в один шаг); инкрементное — изменения с последней любой копии (быстро копировать, долго восстанавливать цепочку); дифференциальное — изменения с последнего полного (компромисс: восстановление = полное + одна разностная). Копии хранят отдельно от сервера; вместе с архивом журнала возможно восстановление на момент времени (point-in-time). Репликация — поддержание копий БД на нескольких узлах (синхронная — гарантия идентичности, асинхронная — скорость): отказоустойчивость и разгрузка чтения.

Стратегии копирования на календаре. Полная копия — в воскресенье; сбой — в четверг утром. Что читать при восстановлении?

СтратегияЧто снималось Пн–СрВосстановление после сбоя в Чт
только полныеничего (следующая — в Вс)полная Вс → потеряны Пн–Ср
инкрементнаяПн: изм. за Пн; Вт: за Вт; Ср: за Срполная Вс + три инкремента по порядку
дифференциальнаяПн: изм. с Вс; Вт: изм. с Вс; Ср: изм. с Всполная Вс + одна копия за Ср

Инкрементная быстрее снимается, но цепочка восстановления длиннее (и рвётся, если потерян один файл); дифференциальная растёт день ото дня, зато восстановление — в два шага. Добавив архив журнала после Ср, можно докатиться до момента прямо перед сбоем (point-in-time recovery).

Вопросы к собеседованию

Как устроен хешированный файл? Что такое коллизии и как их разрешают?

Адрес записи вычисляется хеш-функцией от значения ключа — поиск по ключу почти O(1) без индекса. Коллизия — разные ключи дают один адрес; разрешение: цепочки (область переполнения со списками) или открытая адресация (поиск следующего свободного места). Недостатки: неэффективный диапазонный поиск и деградация при заполнении.

Почему индексы СУБД строят на B-деревьях (B⁺-деревьях)?

B-дерево — сбалансированное многоветвистое дерево: узел содержит десятки–сотни ключей и подгоняется под размер дискового блока, поэтому поиск требует лишь нескольких обращений к диску (O(log n) с большим основанием); все листья на одной глубине, дерево само балансируется при вставках. В B⁺-дереве данные в листьях, связанных списком, — эффективен и точечный, и диапазонный поиск.

Какими средствами обеспечивается целостность базы данных?

Целостность сущностей — PRIMARY KEY (уникальность, не NULL); ссылочная — FOREIGN KEY с правилами ON DELETE/UPDATE (RESTRICT, CASCADE, SET NULL); доменные ограничения — типы, NOT NULL, CHECK, UNIQUE; триггеры для сложных правил. Ограничения проверяет сама СУБД, а не приложение.

Что такое транзакция и свойства ACID?

Транзакция — неделимая последовательность операций, переводящая БД из одного согласованного состояния в другое (COMMIT/ROLLBACK). ACID: атомарность — всё или ничего; согласованность — ограничения не нарушаются; изоляция — параллельные транзакции не видят промежуточных состояний друг друга; долговечность — зафиксированные изменения переживают сбой (журнал с упреждающей записью, контрольные точки).

Как защищают базы данных от несанкционированного доступа?

Аутентификация пользователей СУБД; система привилегий GRANT/REVOKE на объекты и операции; представления и хранимые процедуры, скрывающие лишние данные; шифрование хранимых данных и соединений; аудит действий; резервное копирование как защита от потери. Дополняется мерами уровня ОС и сети.