БД:Теория:Глава 3: различия между версиями
Zhabka (обсуждение | вклад) м Пофиксил неправильный перенос таблички из markdown Метка: визуальный редактор отключён |
Zhabka (обсуждение | вклад) м Добавлены метки на дальнейшее исправление |
||
Строка 18: | Строка 18: | ||
# '''Выборка (Selection, σ):''' Выбирает кортежи (строки) из отношения, удовлетворяющие заданному условию (предикату <code>φ</code>). | # '''Выборка (Selection, σ):''' Выбирает кортежи (строки) из отношения, удовлетворяющие заданному условию (предикату <code>φ</code>). | ||
#* '''Обозначение:''' <code>σ<0xCF><0x86>(R)</code> - выбрать строки из отношения R, где условие <code>φ</code> истинно. | #* '''Обозначение:''' <code>σ<0xCF><0x86>(R)</code> !TODO! - выбрать строки из отношения R, где условие <code>φ</code> истинно. | ||
#* '''SQL аналог:''' Условие в секции <code>WHERE</code>. | #* '''SQL аналог:''' Условие в секции <code>WHERE</code>. | ||
#* '''Пример:''' Выбрать студентов группы ‘3100’, чей ID >= 150000. | #* '''Пример:''' Выбрать студентов группы ‘3100’, чей ID >= 150000. | ||
Строка 24: | Строка 24: | ||
#** Рел. Алгебра: <code>σ(STUDENTS.GROUP='3100')∧(STUDENTS.ID>=150000)(STUDENTS)</code> ''(Здесь <code>∧</code> означает логическое “И”)'' | #** Рел. Алгебра: <code>σ(STUDENTS.GROUP='3100')∧(STUDENTS.ID>=150000)(STUDENTS)</code> ''(Здесь <code>∧</code> означает логическое “И”)'' | ||
# '''Проекция (Projection, π):''' Выбирает указанные атрибуты (столбцы) из отношения, удаляя дубликаты строк в результирующем отношении. | # '''Проекция (Projection, π):''' Выбирает указанные атрибуты (столбцы) из отношения, удаляя дубликаты строк в результирующем отношении. | ||
#* '''Обозначение:''' <code>π<0xD0><0xB0><0xD1><0x82><0xD1><0x80><0xD0><0xB8><0xD0><0xB1><0xD1><0x83><0xD1><0x82><0xD1><0x8B>(R)</code> - выбрать столбцы <code><атрибуты></code> из отношения R. | #* '''Обозначение:''' <code>π<0xD0><0xB0><0xD1><0x82><0xD1><0x80><0xD0><0xB8><0xD0><0xB1><0xD1><0x83><0xD1><0x82><0xD1><0x8B>(R)</code> - выбрать столбцы <code><атрибуты></code> из отношения R. !TODO! | ||
#* '''SQL аналог:''' Список столбцов в секции <code>SELECT</code>. Удаление дубликатов соответствует <code>SELECT DISTINCT</code>. | #* '''SQL аналог:''' Список столбцов в секции <code>SELECT</code>. Удаление дубликатов соответствует <code>SELECT DISTINCT</code>. | ||
#* '''Пример:''' Получить имена и группы всех студентов. | #* '''Пример:''' Получить имена и группы всех студентов. | ||
Строка 167: | Строка 167: | ||
* '''Тривиальная ФЗ:''' Зависимость вида <code>A → B</code>, где <code>B</code> является подмножеством <code>A</code>. Например, <code>{StudID, StudName} → StudName</code>. Такие зависимости выполняются всегда и не несут полезной информации для нормализации. Обычно рассматривают только '''нетривиальные''' ФЗ. | * '''Тривиальная ФЗ:''' Зависимость вида <code>A → B</code>, где <code>B</code> является подмножеством <code>A</code>. Например, <code>{StudID, StudName} → StudName</code>. Такие зависимости выполняются всегда и не несут полезной информации для нормализации. Обычно рассматривают только '''нетривиальные''' ФЗ. | ||
* '''Полная ФЗ:''' Зависимость <code>A → B</code>, где <code>A</code> – составной детерминант (несколько атрибутов), и <code>B</code> не зависит ни от какого ''подмножества'' <code>A</code>. Мы уже обсуждали это в контексте 2НФ. | * '''Полная ФЗ:''' Зависимость <code>A → B</code>, где <code>A</code> – составной детерминант (несколько атрибутов), и <code>B</code> не зависит ни от какого ''подмножества'' <code>A</code>. Мы уже обсуждали это в контексте 2НФ. !TODO! | ||
* '''Частичная ФЗ:''' Зависимость <code>A → B</code>, где <code>A</code> – составной детерминант, и <code>B</code> зависит от ''части'' <code>A</code>. (Пример: <code>{StudID, ExamID} → StudName</code>, но при этом <code>StudID → StudName</code>. Здесь <code>StudName</code> частично зависит от ключа). | * '''Частичная ФЗ:''' Зависимость <code>A → B</code>, где <code>A</code> – составной детерминант, и <code>B</code> зависит от ''части'' <code>A</code>. (Пример: <code>{StudID, ExamID} → StudName</code>, но при этом <code>StudID → StudName</code>. Здесь <code>StudName</code> частично зависит от ключа). | ||
* '''Транзитивная ФЗ:''' Зависимость <code>A → C</code>, которая существует только через промежуточный атрибут <code>B</code>, такой что <code>A → B</code> и <code>B → C</code>, при этом <code>B</code> не зависит от <code>A</code> (<code>B → A</code> неверно) и <code>B</code> не является частью ключа <code>A</code>. (Пример: <code>StudID → Group</code> и <code>Group → GrMentor</code>, следовательно, <code>StudID → GrMentor</code> транзитивно через <code>Group</code>). | * '''Транзитивная ФЗ:''' Зависимость <code>A → C</code>, которая существует только через промежуточный атрибут <code>B</code>, такой что <code>A → B</code> и <code>B → C</code>, при этом <code>B</code> не зависит от <code>A</code> (<code>B → A</code> неверно) и <code>B</code> не является частью ключа <code>A</code>. (Пример: <code>StudID → Group</code> и <code>Group → GrMentor</code>, следовательно, <code>StudID → GrMentor</code> транзитивно через <code>Group</code>). |
Версия от 06:58, 26 апреля 2025
В предыдущей главе мы научились проектировать структуру базы данных с помощью ER-моделей и создавать таблицы с помощью SQL. Но как убедиться, что полученная структура таблиц (схема) является “хорошей”? Не приведет ли она к проблемам при работе с данными?
Именно для ответа на эти вопросы существует процесс нормализации.
Часть 1: Реляционное представление и Реляционная Алгебра (Краткое Повторение и Дополнение)
Прежде чем говорить о нормализации, вспомним ключевые моменты реляционной модели и введем несколько понятий из реляционной алгебры – формального языка для манипулирования отношениями (таблицами).
- Отношение (Таблица): Набор кортежей (строк).
- Атрибут (Столбец): Имеет имя и домен (тип данных).
- Кортеж (Строка): Набор значений атрибутов.
- Ключ: Атрибут(ы), уникально идентифицирующий кортеж.
Реляционная Алгебра:
Это набор операций над отношениями, результатом которых всегда является новое отношение. Нам понадобятся основные операции для понимания того, как СУБД может выполнять запросы и как устроена нормализация.
- Выборка (Selection, σ): Выбирает кортежи (строки) из отношения, удовлетворяющие заданному условию (предикату
φ
).- Обозначение:
σ<0xCF><0x86>(R)
!TODO! - выбрать строки из отношения R, где условиеφ
истинно. - SQL аналог: Условие в секции
WHERE
. - Пример: Выбрать студентов группы ‘3100’, чей ID >= 150000.
- SQL:
SELECT * FROM STUDENTS WHERE STUDENTS.GROUP = '3100' AND STUDENTS.ID >= 150000;
- Рел. Алгебра:
σ(STUDENTS.GROUP='3100')∧(STUDENTS.ID>=150000)(STUDENTS)
(Здесь∧
означает логическое “И”)
- SQL:
- Обозначение:
- Проекция (Projection, π): Выбирает указанные атрибуты (столбцы) из отношения, удаляя дубликаты строк в результирующем отношении.
- Обозначение:
π<0xD0><0xB0><0xD1><0x82><0xD1><0x80><0xD0><0xB8><0xD0><0xB1><0xD1><0x83><0xD1><0x82><0xD1><0x8B>(R)
- выбрать столбцы<атрибуты>
из отношения R. !TODO! - SQL аналог: Список столбцов в секции
SELECT
. Удаление дубликатов соответствуетSELECT DISTINCT
. - Пример: Получить имена и группы всех студентов.
- SQL:
SELECT DISTINCT name, group FROM STUDENTS;
- Рел. Алгебра:
πname, group(STUDENTS)
- SQL:
- Обозначение:
- Соединение (Join, ⋈): Комбинирует кортежи из двух отношений на основе некоторого условия (
θ
, тета).- Тета-соединение (Theta Join):
R ⋈θ S
. Общий случай, гдеθ
- любое условие сравнения между атрибутами R и S. Логически эквивалентно:σθ(R × S)
(выборка из декартова произведения). - Эквисоединение (Equijoin): Частный случай тета-соединения, где условие
θ
содержит только операции равенства (=
). - Естественное соединение (Natural Join): Эквисоединение по всем атрибутам с одинаковыми именами, причем совпадающие столбцы включаются в результат только один раз.
- SQL аналог: Операторы
JOIN
.INNER JOIN ON условие
соответствует тета-соединению или эквисоединению.NATURAL JOIN
соответствует естественному соединению. - Пример: Соединить студентов и их экзамены по ID студента.
- SQL:
SELECT * FROM STUDENTS JOIN EXAMS ON STUDENTS.ID = EXAMS.STUD_ID;
- Рел. Алгебра:
STUDENTS ⋈STUDENTS.ID=EXAMS.STUD_ID EXAMS
- SQL:
- Тета-соединение (Theta Join):
Законы Реляционной Алгебры (Примеры Эквивалентных Преобразований):
СУБД использует правила эквивалентности для преобразования запроса в различные планы выполнения, чтобы выбрать наиболее эффективный.
- Соединение коммутативно (для
INNER JOIN
):R ⋈θ S ≡ S ⋈θ R
- Соединение ассоциативно (для
INNER JOIN
):R ⋈θ (S ⋈φ T) ≡ (R ⋈θ S) ⋈φ T
- Каскад выборок:
σθ∧φ(R) ≡ σθ(σφ(R))
- “Проталкивание” выборки через соединение: Если условие
φ
относится только к атрибутамR
, то:σφ(R ⋈θ S) ≡ (σφ(R)) ⋈θ S
. Это важное правило оптимизации: выполнять выборку как можно раньше, чтобы уменьшить размер данных для соединения. - “Проталкивание” проекции через соединение (сложнее):
πA(R ⋈θ S)
можно преобразовать, оставив вR
иS
только те атрибуты, которые нужны для результата (A
) и для условия соединения (θ
). Тоже важное правило: отбрасывать ненужные столбцы как можно раньше.
План Выполнения Запроса:
Это последовательность операций реляционной алгебры (и конкретных алгоритмов их выполнения), которую СУБД строит для ответа на SQL-запрос. Часто представляется в виде дерева операций. Для одного SQL-запроса может существовать несколько эквивалентных планов (дающих одинаковый результат), но с разной стоимостью выполнения. Оптимизатор запросов выбирает план с наименьшей предполагаемой стоимостью.
Пример одного из возможных планов для запроса SELECT * FROM STUDENTS ST JOIN EXAMS EXAM ON ST.ID = EXAM.STUD_ID WHERE ST.GROUP = '3100' AND ST.ID >= 150000;
Часть 2: Проблемы Плохого Дизайна и Аномалии
Зачем нам вообще нужна нормализация, если мы можем просто создать одну большую таблицу со всеми нужными данными? Рассмотрим таблицу STUDENTS
с информацией о студентах, их группах и кураторах (GrMentor - Куратор Группы).
Таблица STUDENTS
(Ненормализованная)
StudID | StudName | Group | GrMentor |
---|---|---|---|
1 | Ivan Petrov | P3100 | Egor Kirov |
3 | Vasily Ivanov | P3101 | Roman Ivov |
34 | Gleb Anisimov | P3100 | Egor Kirov |
Проблемы:
Избыточность Данных: Информация о кураторе (
GrMentor
) повторяется для каждого студента из одной и той же группы (Egor Kirov для группы P3100). Это ведет к неэффективному использованию памяти.Аномалии Обновления (Update Anomalies): Если куратор группы P3100 сменится, нам придется обновить поле
GrMentor
во всех строках, гдеGroup = 'P3100'
. Если мы обновим не все строки, данные станут противоречивыми (у одной группы окажется несколько кураторов).-- Попытка сменить куратора только для одного студента UPDATE STUDENTS SET GrMentor = 'Eugene Lomov' WHERE StudName = 'Ivan Petrov';
Результат (Несогласованность):
StudID StudName Group GrMentor 1 Ivan Petrov P3100 Eugene Lomov (Это новый куратор) 3 Vasily Ivanov P3101 Roman Ivov 34 Gleb Anisimov P3100 Egor Kirov (А тут остался старый) Аномалии Вставки (Insertion Anomalies):
- Мы не можем добавить информацию о новой группе и ее кураторе, пока в этой группе нет хотя бы одного студента (потому что
StudID
, вероятно, часть первичного ключа или просто идентификатор студента, который не может бытьNULL
для информации о группе). - При добавлении нового студента в существующую группу, мы должны правильно указать ее куратора. Ошибка при вводе имени куратора приведет к несогласованности (см. пример со слайда 26, где
E.Kirov
иEgor Lomov
могут быть одним человеком).
-- Попытка добавить студентов с разными написаниями куратора INSERT INTO STUDENTS VALUES(57, 'Nina Simonova', 'P3100', 'E. Kirov'); INSERT INTO STUDENTS VALUES(58, 'Petr Uvarov', 'P3100', 'Egor Lomov');
- Мы не можем добавить информацию о новой группе и ее кураторе, пока в этой группе нет хотя бы одного студента (потому что
Аномалии Удаления (Deletion Anomalies): Если мы удалим последнего студента из какой-либо группы (например, Василия Иванова из P3101), мы потеряем информацию о самой группе P3101 и ее кураторе Романе Ивове, даже если эта информация нам еще нужна.
DELETE FROM STUDENTS WHERE StudName = 'Vasily Ivanov';
После этого запроса информация о группе P3101 и ее кураторе исчезнет из таблицы.
Все эти проблемы возникают из-за того, что в одной таблице смешаны данные о разных сущностях (студенты и группы/кураторы) и существуют “неправильные” зависимости между атрибутами. Нормализация помогает выявить и устранить эти проблемы.
Часть 3: Функциональные Зависимости (ФЗ)
Ключевое понятие для нормализации.
- Функциональная зависимость (Functional Dependency, FD) описывает смысловую связь между атрибутами внутри одного отношения (таблицы).
- Говорят, что атрибут (или набор атрибутов)
B
функционально зависит от атрибута (или набора атрибутов)A
, если для каждого возможного значенияA
существует ровно одно соответствующее значениеB
. - Обозначение:
A → B
(читается “A функционально определяет B” или “B функционально зависит от A”). A
называется детерминантом.
Важно: ФЗ определяются смыслом данных (семантикой) предметной области, а не текущими данными в таблице!
Примеры ФЗ для таблицы STUDENTS
(StudID, StudName, Group, GrMentor):
StudID → StudName
(По ID студента однозначно определяется его имя).StudID → Group
(По ID студента однозначно определяется его группа).StudID → GrMentor
(По ID студента можно узнать его группу, а по группе - куратора, т.е. косвенно ID определяет куратора).Group → GrMentor
(По номеру группы однозначно определяется ее куратор. Предполагаем, что у группы только один куратор).StudID, Group → GrMentor
(Тоже верно, но избыточно, т.к.Group
уже зависит отStudID
).
Примеры НЕ ФЗ:
Group → StudID
(Неверно, т.к. в одной группе много студентов).StudName → StudID
(Неверно, т.к. могут быть тезки).
Типы ФЗ:
- Тривиальная ФЗ: Зависимость вида
A → B
, гдеB
является подмножествомA
. Например,{StudID, StudName} → StudName
. Такие зависимости выполняются всегда и не несут полезной информации для нормализации. Обычно рассматривают только нетривиальные ФЗ. - Полная ФЗ: Зависимость
A → B
, гдеA
– составной детерминант (несколько атрибутов), иB
не зависит ни от какого подмножестваA
. Мы уже обсуждали это в контексте 2НФ. !TODO! - Частичная ФЗ: Зависимость
A → B
, гдеA
– составной детерминант, иB
зависит от частиA
. (Пример:{StudID, ExamID} → StudName
, но при этомStudID → StudName
. ЗдесьStudName
частично зависит от ключа). - Транзитивная ФЗ: Зависимость
A → C
, которая существует только через промежуточный атрибутB
, такой чтоA → B
иB → C
, при этомB
не зависит отA
(B → A
неверно) иB
не является частью ключаA
. (Пример:StudID → Group
иGroup → GrMentor
, следовательно,StudID → GrMentor
транзитивно черезGroup
).
Аксиомы Армстронга: Формальные правила для вывода новых ФЗ из существующих:
- Рефлексивность: Если
B ⊆ A
, тоA → B
. (Тривиальная зависимость). - Дополнение (Augmentation): Если
A → B
, тоA, C → B, C
. (Добавление атрибутаC
к обеим частям). - Транзитивность: Если
A → B
иB → C
, тоA → C
.
Эти аксиомы позволяют формально вывести все возможные ФЗ для отношения, зная некоторый начальный набор.
Часть 4: Нормальные Формы
Процесс нормализации заключается в последовательном приведении таблиц к нормальным формам более высокого порядка. Каждая следующая нормальная форма накладывает более строгие ограничения.
Ненормализованная Форма (UNF / 0NF): Таблица содержит неатомарные значения (повторяющиеся группы, списки в ячейках). Это нарушает основные принципы реляционной модели.
Пример (из слайда 38):
StudID | StudName | ExamID | ExamName | ExDate | ProfID | ProfName |
---|---|---|---|---|---|---|
123 | Ivan Ivanov | 34 | OPD | 14.01.19 | 55 | Rebrov A. |
78 | DBMS | 29.12.20 | 789 | Uvarov S. | ||
345 | Egor Kirov | 34 | OPD | 14.01.19 | 55 | Rebrov A. |
87 | History | 25.01.19 | 342 | Serov G. |
Здесь у одного студента несколько экзаменов, дат, преподавателей - значения неатомарны.
Первая Нормальная Форма (1НФ):
- Правило: Отношение находится в 1НФ, если все его атрибуты содержат только атомарные (неделимые) значения. На пересечении строки и столбца - ровно одно значение из домена.
Как достичь: 1. (Плохой способ) “Расплющить” таблицу: Создать отдельную строку для каждого значения из повторяющейся группы. Это приводит к сильной избыточности. Пример (из слайда 40):
StudID | StudName | ExamID | ExamName | ExDate | ProfID | ProfName |
---|---|---|---|---|---|---|
123 | Ivan Ivanov | 34 | OPD | 14.01.19 | 55 | Rebrov A. |
123 | Ivan Ivanov | 78 | DBMS | 29.12.20 | 789 | Uvarov S. |
345 | Egor Kirov | 34 | OPD | 14.01.19 | 55 | Rebrov A. |
345 | Egor Kirov | 87 | History | 25.01.19 | 342 | Serov G. |
Теперь значения атомарны, но информация о студенте Иванове и Кирове дублируется.
- (Хороший способ) Декомпозиция: Разделить таблицу на несколько, вынеся повторяющиеся группы в отдельную таблицу со связью через внешний ключ. Пример (из слайда 41):
Таблица STUDENTS
StudID (PK) | StudName |
---|---|
123 | Ivan Ivanov |
345 | Egor Kirov |
Таблица EXAMS
StudID (FK) | ExamID | ExamName | ExDate | ProfID | ProfName |
---|---|---|---|---|---|
123 | 34 | OPD | 14.01.19 | 55 | Rebrov A. |
123 | 78 | DBMS | 29.12.20 | 789 | Uvarov S. |
345 | 34 | OPD | 14.01.19 | 55 | Rebrov A. |
345 | 87 | History | 25.01.19 | 342 | Serov G. |
Теперь обе таблицы в 1НФ.
Вторая Нормальная Форма (2НФ):
- Правило: Отношение находится в 2НФ, если оно находится в 1НФ и все неключевые атрибуты полностью функционально зависят от каждого потенциального ключа. (Нет частичных зависимостей от ключа).
- Актуально для таблиц с составными первичными ключами.
- Цель: Устранить избыточность, возникающую из-за того, что неключевой атрибут зависит только от части составного ключа.
- Как достичь: Вынести частично зависимые атрибуты и ту часть ключа, от которой они зависят, в отдельную таблицу.
Пример (используем “расплющенную” таблицу из 1НФ):
- Первичный ключ:
{StudID, ExamID}
. - Неключевые атрибуты:
StudName
,ExamName
,ExDate
,ProfID
,ProfName
. - Частичные зависимости:
StudID → StudName
(Зависит только от части ключа -StudID
).ExamID → ExamName
(Зависит только от части ключа -ExamID
).
- Полные зависимости:
{StudID, ExamID} → ExDate
(Предполагаем, что дата зависит от студента и экзамена).{StudID, ExamID} → ProfID
(Предполагаем, что преподаватель зависит от студента и экзамена).
- Другие зависимости:
ProfID → ProfName
(Имя преподавателя зависит от его ID).
Таблица не в 2НФ из-за частичных зависимостей StudName
и ExamName
.
Декомпозиция для 2НФ:
- Выносим
StudID → StudName
:- Новая таблица
STUDENTS
:{StudID (PK), StudName}
. - Старая таблица (переименуем в
EXAMS_PARTICIPATION
):{StudID (FK), ExamID (PK), ExamName, ExDate, ProfID, ProfName}
. (StudName удален).
- Новая таблица
- Выносим
ExamID → ExamName
изEXAMS_PARTICIPATION
:- Новая таблица
EXAMS
:{ExamID (PK), ExamName}
. - Таблица
EXAMS_PARTICIPATION
:{StudID (FK), ExamID (FK), ExDate, ProfID, ProfName}
. (ExamName удален). Первичный ключ теперь{StudID, ExamID}
.
- Новая таблица
Результат (все таблицы в 2НФ):
Таблица STUDENTS
StudID (PK) | StudName |
---|---|
123 | Ivan Ivanov |
345 | Egor Kirov |
Таблица EXAMS
ExamID (PK) | ExamName |
---|---|
34 | OPD |
78 | DBMS |
87 | History |
Таблица EXAMS_PARTICIPATION
StudID (FK, PK) | ExamID (FK, PK) | ExDate | ProfID | ProfName |
---|---|---|---|---|
123 | 34 | 14.01.19 | 55 | Rebrov A. |
123 | 78 | 29.12.20 | 789 | Uvarov S. |
345 | 34 | 14.01.19 | 55 | Rebrov A. |
345 | 87 | 25.01.19 | 342 | Serov G. |
Третья Нормальная Форма (3НФ):
- Правило: Отношение находится в 3НФ, если оно находится в 2НФ и все неключевые атрибуты нетранзитивно зависят от каждого потенциального ключа. (Нет транзитивных зависимостей неключевых атрибутов от ключа через другие неключевые атрибуты).
- Цель: Устранить избыточность, возникающую из-за того, что неключевой атрибут зависит от другого неключевого атрибута.
- Как достичь: Вынести транзитивно зависимые атрибуты и их непосредственный детерминант в отдельную таблицу.
Пример (используем таблицы из 2НФ):
- В таблицах
STUDENTS
иEXAMS
нет транзитивных зависимостей (там просто ключ и один неключевой атрибут). - Рассмотрим
EXAMS_PARTICIPATION
:- Первичный ключ:
{StudID, ExamID}
. - Неключевые атрибуты:
ExDate
,ProfID
,ProfName
. - Зависимости:
{StudID, ExamID} → ExDate
(Полная){StudID, ExamID} → ProfID
(Полная)ProfID → ProfName
(Зависимость между неключевыми атрибутами!)
- Транзитивная зависимость:
{StudID, ExamID} → ProfID
иProfID → ProfName
, следовательно,ProfName
транзитивно зависит от первичного ключа черезProfID
.
- Первичный ключ:
Таблица EXAMS_PARTICIPATION
не в 3НФ.
Декомпозиция для 3НФ:
- Выносим
ProfID → ProfName
изEXAMS_PARTICIPATION
:- Новая таблица
PROFS
:{ProfID (PK), ProfName}
. - Таблица
EXAMS_PARTICIPATION
:{StudID (FK, PK), ExamID (FK, PK), ExDate, ProfID (FK)}
. (ProfName удален, ProfID остался как внешний ключ кPROFS
).
- Новая таблица
Результат (все таблицы в 3НФ):
Таблица STUDENTS
(без изменений) Таблица EXAMS
(без изменений)
Таблица PROFS
ProfID (PK) | ProfName |
---|---|
55 | Rebrov A. |
789 | Uvarov S. |
342 | Serov G. |
Таблица EXAMS_PARTICIPATION
StudID (FK, PK) | ExamID (FK, PK) | ExDate | ProfID (FK) |
---|---|---|---|
123 | 34 | 14.01.19 | 55 |
123 | 78 | 29.12.20 | 789 |
345 | 34 | 14.01.19 | 55 |
345 | 87 | 25.01.19 | 342 |
Нормальная Форма Бойса-Кодда (НФБК / BCNF):
- Более строгая версия 3НФ.
- Правило: Отношение находится в НФБК, если для каждой нетривиальной функциональной зависимости
A → B
, детерминантA
является суперключом (т.е. содержит в себе потенциальный ключ). - Большинство таблиц в 3НФ также находятся и в НФБК. Проблемы могут возникнуть при наличии нескольких перекрывающихся потенциальных ключей.
- Часто является конечной целью нормализации на практике.
Высшие нормальные формы (4НФ, 5НФ): Существуют и другие нормальные формы (4НФ, 5НФ, DKNF), которые решают более тонкие проблемы, связанные с многозначными зависимостями и зависимостями соединения. На практике они используются редко. Обычно достаточно достичь 3НФ или НФБК.
Часть 5: Денормализация
Иногда, после приведения базы данных к высокой нормальной форме (например, 3НФ или НФБК), оказывается, что для выполнения частых запросов требуется слишком много операций соединения (JOIN
) между таблицами. Это может снижать производительность.
В таких случаях иногда прибегают к денормализации — процессу осознанного нарушения некоторых правил нормализации для повышения производительности запросов.
- Прием: Объединение нескольких таблиц в одну, добавление избыточных данных.
- Плюсы:
- Уменьшение количества соединений в запросах.
- Потенциальное ускорение выполнения частых запросов на чтение.
- Минусы:
- Увеличение избыточности данных (занимает больше места).
- Повышенный риск аномалий (вставки, обновления, удаления).
- Требуется больше усилий для поддержания целостности данных (например, с помощью триггеров или на уровне приложения).
Денормализацию следует применять осторожно, только после тщательного анализа производительности и понимания всех рисков. Обычно она является оправданной в системах с преобладанием операций чтения (например, в хранилищах данных для аналитики), где скорость выборки критически важна.