- •Введение
- •Глава 1. Основные понятия баз данных
- •1.1. История возникновения баз данных
- •1.2. Модели данных
- •1.2.1. Иерархическая модель данных
- •1.2.2. Сетевая модель базы данных
- •1.2.3. Реляционная модель базы данных
- •1.2.4. Другие модели баз данных (ООСУБД)
- •2.1. История появления и развития SQL
- •Глава 2. SQL
- •2.2. Стандарты SQL
- •2.2.1. Стандарты ANSI/ISO
- •2.2.2. ODBC и консорциум SQL Access Group
- •2.2.3. JDBC и серверы приложений
- •2.3. SQL и переносимость
- •2.4. SQL и сети
- •2.4.1. Централизованная архитектура
- •2.4.2. Архитектура файлового сервера
- •2.4.3. Архитектура “клиент/сервер”
- •2.4.4. Многоуровневая архитектура
- •2.4.5. SQL и мэйнфреймы
- •2.4.7. SQL и UNIX
- •2.4.8. SQL и персональные компьютеры
- •2.4.9. SQL, хранилища данных и интеллектуальные ресурсы предприятия
- •2.4.10. SQL и интернет-приложения
- •2.5. Основы SQL
- •2.5.1. Использование SQL для извлечения информации из таблиц
- •2.5.2. Команда SELECT
- •2.5.3. Создание более сложных предикатов в предложении SELECT
- •2.5.4. Формирование вывода запросов
- •2.5.5. Агрегатные группы
- •2.6. Запросы к нескольким таблицам
- •2.6.1. Подзапросы
- •2.6.2. Использование операторов ANY, ALL и SOME
- •2.6.3. Использование предложения UNION
- •2.6.4. Ввод, удаление и изменение значения поля
- •2.7. DDL (Язык описания данных)
- •2.7.1. Создание таблиц
- •2.7.2. Индексы
- •2.7.3. Изменение структуры таблицы после ее создания
- •2.8. Ограничение данных
- •2.8.1. Ограничение таблиц
- •2.8.2. Установка значений по умолчанию
- •2.9. Поддержка целостности данных
- •2.9.1. Первичные ключи
- •2.9.2. Пользовательские представления
- •2.10. Модификация данных с помощью представлений
- •2.11. Разграничение доступа в базе данных
- •Глава 3. Математические основы реляционных баз данных
- •3.1. Отношения и их схемы
- •3.2. Реляционные операторы
- •3.2.1. Булевы операции
- •3.2.2. Оператор выбора
- •3.2.3. Оператор проекции
- •3.2.4. Оператор соединения
- •3.2.5. Другие операции на отношениях
- •3.2.6. Оператор деления
- •3.2.7. Оператор переименования атрибутов
- •3.2.8. Оператор эквисоединения
- •3.2.9. Расширения для сравнения на доменах
- •3.2.9.1. Расширение выбора
- •3.3. Реляционная алгебра
- •3.3.1. Дополнительные операторы
- •3.3.1.1. Оператор расщепления
- •3.3.1.2. Оператор FACTOR
- •3.4. Функциональные зависимости
- •3.4.1. Определение
- •3.4.2. Аксиомы вывода
- •3.4.3. Применение аксиом вывода
- •3.4.4. Выводы на основе аксиом вывода
- •3.4.6. Направленные ациклические графы вывода
- •3.4.7. Проверка принадлежности к замыканию множества функциональных зависимостей
- •3.5. Покрытия функциональных зависимостей
- •3.5.1. Покрытия и эквивалентность
- •3.5.2. Неизбыточные покрытия
- •3.5.3. Редуцированные покрытия
- •3.5.3.1. Посторонние атрибуты
- •3.5.3.3. Алгоритм построения редуцированного покрытия
- •3.5.3.4. Канонические покрытия
- •3.5.3.5. Структура неизбыточных покрытий
- •3.5.4. Минимальные покрытия
- •3.5.4.1. Прямая определяемость
- •3.5.4.2. Вычисление минимальных покрытий
- •3.5.4.3. Оптимальные покрытия
- •3.5.5. Составные функциональные зависимости
- •3.5.6. Кольцевые покрытия
- •3.6. Многозначные зависимости и зависимости соединения
- •3.6.1. Многозначные зависимости
- •3.6.2. Многозначные и функциональные зависимости
- •3.6.3. Аксиомы вывода для многозначных зависимостей
- •3.6.4. Только многозначные зависимости
- •3.6.5. Функциональные и многозначные зависимости
- •3.6.6. Зависимости соединения
- •3.7. Синтез схем реляционных баз данных
- •3.7.1. Базы данных и их схемы
- •3.7.2. Нормальные формы баз данных
- •3.7.2.1. Первая нормальная форма
- •3.7.2.2. Вторая нормальная форма
- •3.7.2.4. Нормальная форма Бойса - Кодда (НФБК)
- •3.7.2.5. Четвертая нормальная форма
- •3.7.2.3. Третья нормальная форма
- •3.8. Алгоритмы синтеза схем баз данных
- •3.8.1. Нормализация через декомпозицию
- •3.8.2. Недостатки нормализации через декомпозицию
- •3.8.3. Нормализация посредством синтеза
- •Глава 4. Система управления базами данных PostgreSQL
- •4.1. Установка
- •4.2. Запуск и останов сервера PostgreSQL
- •4.2.1. Утилита psql
- •4.2.2. Создание базы данных
- •4.3. Объекты базы данных
- •4.4. Функции и операторы
- •4.4.1. Логические операторы
- •4.4.2. Операторы сравнения
- •4.5. Клиентские приложения PostgreSQL
- •4.5.1. clusterdb
- •4.5.2. createdb
- •4.5.3. createuser
- •4.5.4. dropdb
- •4.5.5. dropuser
- •4.5.6. ecpg
- •4.5.7. pg_basebackup
- •4.5.8. pgbench
- •4.5.9. pg_config
- •4.5.10. pg_dump
- •4.5.11. pg_dumpall
- •4.5.12. pg_isready
- •4.5.13. pg_receivewal
- •4.5.14. pg_restore
- •4.5.15. psql
- •4.5.16. reindexdb
- •4.5.17. vacuumdb
- •4.6. Серверные приложения PostgreSQL
- •4.6.1. initdb
- •4.6.2. pg_archivecleanup
- •4.6.3. pg_checksums
- •4.6.4. pg_controldata
- •4.6.6. pg_resetwal
- •4.6.7. pg_rewind
- •4.6.8. pg_test_fsync
- •4.6.9. pg_test_timing
- •4.6.10. pg_upgrade
- •4.6.11. pg_waldump
- •4.6.12. postgres
- •4.6.13. postmaster
- •4.7. Серверное программирование
- •4.7.1. Расширение SQL
- •4.7.2. Триггеры
- •Заключение
- •Библиографический список
|
|
- 95 - |
|
|
|
3 |
|
Да |
|
|
|
1 |
ABEIGHJ |
ABEIGH |
Действительно, данный алгоритм строит DDA-граф для зависимости X→X+. На основе данного алгоритма можно построить простой алгоритм для проверки принадлежности зависимости X→Y к замыканию множества функциональных зависимостей F.
MEMBER(F,X→Y) begin
if Y CLOSURE(X, F)
then return(ИСТИНА)
end.
Если рассматривать алгоритм MEMBER с точки зрения производительности, то очевидно, что его временная сложность такая же, как и у алгоритма CLOSURE, который является его основой.
Основные работы по повышению производительности систем автоматизации проектирования схем реляционных баз данных связаны
смодификацией именно алгоритма CLOSURE.
3.5.Покрытия функциональных зависимостей
Впредыдущих разделах были рассмотрены функциональные зависимости и способы их выделения на основе анализа исходных данных. Однако один и тот же набор данных может быть описан с помощью различных наборов функциональных зависимостей. Например, каждая зависимость из множества F = {AB→BC, A→C, A→B, B→C, AC→B} может быть выведена из множества G = {A→B, B→C}. Таким образом, можно рассматривать второе множество как более компактное представление первого множества. Следует рассмотреть, по какой причине более выгодно пользоваться короткой записью множества зависимостей.
Все рассмотренные ранее алгоритмы имеют временную сложность, зависящую от количества рассматриваемых в них функциональных зависимостей. Естественно, чем меньше зависимостей рассматривается, тем быстрее алгоритм будет работать.
Всистемах баз данных меньшее количество зависимостей позволяет значительно уменьшить количество проверок, необходимых для поддержания целостности данных.
3.5.1. Покрытия и эквивалентность
Ранее рассматривалось понятие замыкания множества функциональных зависимостей F+, которое можно получить, многократно применяя аксиомы вывода до тех пор, пока новые
- 96 -
зависимости не перестанут добавляться к рассматриваемому множеству. На этом и базируется определение эквивалентности множеств функциональных зависимостей.
Два множества функциональных зависимостей F и G над схемой R эквивалентны (F G), если F+ = G+.
Если два множества зависимостей F и G эквивалентны, то F есть покрытие G, а G - покрытие F.
Если рассматривать определение чисто формально, то понятие покрытия не связано с размером эквивалентных множеств, в то время как нас реально будут интересовать множества с меньшим количеством зависимостей, атрибутных символов и так далее.
С другой стороны, если мы имеем F ≡ G, то F+ = G+, откуда следует, что наличие любой зависимости X→Y в F требует его выводимости из G. С одной зависимости такой вывод можно распространить на все множество и сделать заключение о том, что F G. Симметричность определения эквивалентности приводит к тому, что справедливо и следующее утверждение: G F.
Поскольку F+ включает каждую зависимость X→Y, выводимую из F, то из F G следует, что G F+, а после применения операции замыкания и к левой и к правой частям неравенства получаем G+ (F+) +, зная, что (F+)+ = F+, получаем G+ F+. Проведя аналогичные рассуждения для G+ получим G+ F+. Из этого следует лемма, которую можно сформулировать следующим образом:
Лемма. Для двух множеств функциональных зависимостей F и G над схемой R тождество F G имеет место тогда, и только тогда, когда F G и G F.
Рассмотрим пример. Даны множество F={A→BC, A→D, CD→E} и множество G={A→BCE, A→ABD, CD→E}. Последние зависимости из множеств равны, следовательно, необходимо проверить только выводимость первых зависимостей обоих множеств.
Первоначально будем рассматривать выводимость зависимостей F из G: зависимость A→BCE A→BC (проективность), а A→ABD A→BC (тоже проективность). Таким образом, доказано, что все зависимости из F выводятся из множества G.
Выведем A→BCE:
1)A→BC (дано);
2)A→D (дано);
3){A→BC, A→D} A→BCD (аддитивность из 1 и 2);
-97 -
4)A→BCD A→CD (проективность из 3);
5)CD→E (дано);
6){A→CD, CD→E} A→E (транзитивность из 4 и 5);
7){A→BC, A→E} A→BCE (аддитивность из 1 и 6). Теперь осталось вывести зависимость A→ABD:
1)A→A (рефлексивность);
2)A→BC (дано);
3)A→BC A→B (проективность из 2);
4)A→AB (аддитивность из 1 и 3);
5)A→D (дано);
6)A→ABD (аддитивность из 3 и 5).
Рассмотренная лемма лежит в основе алгоритма проверки
выводимости одного множества функциональных (G) зависимостей из другого (F). Алгоритм возвращает логическое значение «истина», если множество F действительно выводится из F, и «ложь» в противном случае.
DERIVES(F,G) begin
v := «истина»
for каждая зависимость X→Y G do v := v and MEMBER(F,X→Y);
return (v) end.
Рассмотренный алгоритм применяется в другом алгоритме, который позволяет определить уже эквивалентность множеств F и G. На входе алгоритма также множества функциональных зависимостей, для которых по очереди проверяется выводимость друг из друга, а возвращается логическое значение «истина» в том случае, когда выполняется условие F ≡ G.
EQUIV(F,G) begin
v := DERIVES(F,G) and DERIVES(F,G); return (v)
end.
3.5.2. Неизбыточные покрытия
Ранее рассматривался случай, когда два различных множества функциональных зависимостей имели одно и то же замыкание. Однако возможен случай, когда общее замыкание может быть у множества F- зависимостей и его собственного подмножества, что говорит о наличии определенной избыточности у исходного множества. Другими
- 98 -
словами, одну или несколько F-зависимостей можно из него удалить, не изменяя его основного свойства — замыкания.
Множество F-зависимостей F неизбыточно, если оно не имеет такого собственного подмножества F' F, что F' F. В противном случае множество F избыточно.
Пример. F = {AC→B, A→C, A→B, B→C} является избыточным множеством, поскольку из него можно удалить F-зависимость AC→B и получить эквивалентное множество F' = {A→C, A→B, B→C}. Несмотря на то, что F' → F, само множество F' избыточно, поскольку у него самого имеется собственное подмножество F''' = {A→B, B→C}, такое, что F' → F'' и F'' → F'''.
Обратим внимание на то, что F ∩ F' = {AC→B}. Множества различаются только F-зависимостью, удаляемой в процессе нахождения неизбыточного покрытия. Для проверки эквивалентности множеств F ≡ F' достаточно проверять только выводимость зависимостей множества F ∩ F' из множества F'. В примере на первом этапе зависимость AC→B выводится из данной зависимости A→B с использованием аксиомы пополнения F2. На втором этапе зависимость A→C выводится из A→B и B→C с использованием аксиомы F5 (транзитивность).
На основе анализа приведенных рассуждений можно сформулировать еще одно определение избыточности множества F- зависимостей:
Множество F-зависимостей F избыточно, если имеется F- зависимость X Y F такая, что F - {X Y} F, а зависимость X Y называется избыточной в множестве F.
Это определение лежит в основе алгоритма нахождения избыточности множеств функциональных зависимостей, возвращающего логическое значение «истина» в том случае, когда множество избыточно.
REDUNDANT(F) begin
v := «ложь»
for каждая F-зависимость X→Y F do
if MEMBER(F - {X→Y}) then v := «истина»; return(v)
end.
Если мы будем рассматривать любое произвольное множество F- зависимостей, то увидим, что оно обладает свойством конечности, то
- 99 -
есть в него входит конечное множество функциональных зависимостей. После удаления из него избыточной зависимости его размерность уменьшится. В том случае, если множество и после удаления избыточной зависимости осталось избыточным, процесс удаления избыточных зависимостей следует продолжить. Таким образом, процесс получения неизбыточного покрытия носит итерационный характер и будет продолжаться до тех пор, пока не будет найдено неизбыточное покрытие. Процесс абсолютно сходится, потому что исходное множество конечно, а на каждом шаге удаляется по одной зависимости.
В экстремальном случае неизбыточное покрытие может оказаться пустым, если исходное множество содержит только те зависимости, которые выводятся из зависимостей, полученных с помощью аксиомы F1 рефлексивности.
Предположим, что имеется множество F-зависимостей F = на
схеме R = XYA1A2A3...Ai-1AiAi+1...An. Из него могут быть получены F- зависимости вида A1A2A3...Ai-1AiAi+1...An → A1A2A3...Ai-1AiAi+1...An. К таким зависимостям можно применять только аксиомы пополнения и
проективности (F2 и F4). В первом случае будет добавляться атрибут в левую часть F-зависимости, а во втором - удаляться из правой ее части. В обоих случаях правая часть — подмножество левой части F- зависимости.
Рассмотрим, что дает применение других аксиом. Аксиома F3 аддитивности позволяет получать из зависимостей X→Y и X→Z зависимость X→YZ, однако нам известно, что Z X и Y X, следовательно, Z Y X. Опять получена F-зависимость, у которой правая часть - подмножество левой части.
Применение аксиомы F5 транзитивности можно представить, исходя из наших ограничений, следующим образом: {XYZ→YZ, YZ→Z} XYZ→Z, откуда следует, что Z XYZ и полученная зависимость опять имеет правую часть, как подмножество левой.
Аксиома псевдотранзитивности также приводит к аналогичному результату: {XY→Y, WYZ→Z} XYZW→Z. Таким образом, доказана теорема:
Теорема. Если дано множество функциональных зависимостей F= над схемой R и атрибуты X R и Y R, то в замыкание этого множества могут входить только зависимости вида XY Y.
Данная теорема позволяет сделать вывод о том, что F- зависимости в произвольном множестве F можно условно разбить на
- 100 -
два класса: в первый входят зависимости, выводимые на основе аксиомы рефлексивности и имеющие вид XY→Y, и остальные зависимости. Зависимости первого класса всегда могут быть выведены из любого произвольного множества F-зависимостей на схеме R при условии X R и Y R и, следовательно, являются по определению избыточными.
Следствие. Если дано множество функциональных зависимостей F над схемой R и атрибуты X R и Y R, то любая зависимость вида XY Y будет являться избыточной и может быть удалена без изменения замыкания F.
Пример. Дано множество F-зависимостей F = {AB B, A C, A B, B C}. Зависимость AB B избыточна в соответствии со следствием из теоремы, а AC выводится из A→B и B→C (транзитивность).
Теперь можно привести алгоритм, вычисляющий неизбыточное покрытие для множества функциональных зависимостей G, на выходе которого будет множество F как неизбыточное покрытие G.
NONREDUN(G) begin
F := G;
for каждая F-зависимость X Y F do
if (X Y) or MEMBER(F - {X Y}) then F := F - {X Y};
return (F)
end.
Первое условие в операторе if проверяется быстро без вычисления замыкания X, как это требуется для проверки второго условия.
Пример. Дано множество F-зависимостей G={A B, B A, B C, A C}. Результатом работы алгоритма будет множество G ={A B, B A, A C}. Однако при изменении порядка записи зависимостей в множестве G ({A B, B A, A C, B C }) результат работы алгоритма изменится ({A B, B A, B C }) и, следовательно, можно сделать вывод о том, что множество F-зависимостей может иметь несколько неизбыточных покрытий. Кроме того, если G — неизбыточное покрытие F, то вовсе необязательно, чтобы в G входили только зависимости из F (G → F). Так, множество G={A B, B A, AB C} эквивалентно F и неизбыточно, следовательно, оно является неизбыточным покрытием F, хотя зависимость {AB C} F.
