- •Нисходящая денормализация
- •Восходящая денормализация
- •Внутритабличная денормализация
- •Денормализация методом "разделяй и властвуй"
- •Денормализация методом слияния таблиц
- •Вертикальное разбиение таблиц
- •Пример 1.1
- •Горизонтальное разбиение таблиц
- •Разбиение таблиц и ссылочная целостность
- •Пример 1.3.
- •Пример 1.2
Пример 1.2
Таблицей – кандидатом на горизонтальное разбиение является таблица "Проект" (PROJECT), структура которой показана на рис. 1.8. В этой таблице хранятся архивные данные – выполненные проекты.
Рис. 1.8. Таблица "Проект" (PROJECT)
Предположим, что число выполненных проектов в год в организации где-то около 1000. Данные в таблицы нужно хранить 10 лет (10000 записей). Средняя продолжительность проекта равна двум месяцам, т. е. число незавершенных проектов в данный момент времени не превышает 200. Через 5 лет отношение числа текущих проектов к архивным проектам достигнет 0.04.
Следовательно, можно рассмотреть вопрос о горизонтальном разбиении этой таблицы и выполнить его, как показано на рис. 1.9.
Рис. 1.9. Горизонтальное разбиение таблицы "Проект" (PROJECT) на две таблицы: "Текущие проекты" (PROJECT_CUR) и "Архивные проекты" (PROJECT_OLD)
Мы разбили таблицу "Проект" (PROJECT) горизонтально на две таблицы — "Текущие проекты" (PROJECT_CUR) и "Архивные проекты" (PROJECT_OLD).
Разбиение таблиц и ссылочная целостность
Если до разбиения таблица была нормализована, то первичные ключи будут идентичны для таблиц, полученных в результате разбиения. Следовательно, взаимосвязи новых таблиц с другими таблицами базы данных могут остаться такими же, как и с первоначальной таблицей. Однако необходимо рассмотреть и действие правил удаления для исходной таблицы, и участие новой таблицы в существующих взаимоотношениях ссылочной целостности, когда будет решаться вопрос об определении поддержки ссылочной целостности в новых таблицах.
В некоторых случаях может быть проще не определять ссылочную целостность вовсе, так как фактическое удаление строк из новой таблицы будет поддерживаться параллельно с исходной таблицей каким-либо программным способом в приложении БД (например, с помощью триггера).
Пример 1.3.
Для разрешения отношения "многие ко многим" между таблицами "Служащий" (EMPLOYEE) и "Проект" (PROJECT) была введена связывающая таблица "Служащий Проект" (EMP_PROJ), которая имеет ограничения ссылочной целостности, с таблицей "Проект" (PROJECT), как показано на рис. 1.11.
Рис. 1.11. Разрешение отношения "многие ко многим" между таблицами "Служащий" (EMPLOYEE) и "Проект" (PROJECT)
Но у нас теперь, после разбиения таблицы "Проект" (PROJECT), появились две новые таблицы: "Текущие проекты" (PROJECT_CUR) вместо таблицы "Проекты" (PROJECT) и "Архивные проекты" (PROJECT_OLD), как показано на рис. 1.12.
Рис. 1.12. Разрешение отношения "многие ко многим" после разбиения таблицы "Проекты" (PROJECT)
Предположим, что для реализации проекта организация нанимает сотрудников на временной основе (на время выполнения проекта), и вопрос: кто, какие проекты, когда выполнял – не интересует руководство организации. В этом случае взаимосвязь между исполнителями и проектами, которые уже завершены, не интересует руководство, и следовательно, в физической модели данных ничего менять не нужно.
Однако если взаимосвязь между исполнителями и завершенными проектами должна отслеживаться (например, руководство будет изучать вопрос: кто, когда, какой проект выполнял), ее следует распространить и на таблицу "Архивные проекты" (PROJECT_OLD), как показано на рис. 1.13.
Чтобы учесть в БД проделанную нами работу, достаточно внести ограничение внешнего ключа в таблицу "Служащий Проект" (EMP_PROJ), как показано ниже:
Рис. 1.13. Разрешение отношения "многие ко многим" таблицы "Архивные проекты" (PROJECT_OLD)
При разбиении таблицы, для которой были определены ограничения ссылочной целостности, можно также рассмотреть возможность поддержки ссылочной целостности установлением взаимосвязи "один к одному" в сторону исходной таблицы от новой таблицы. В этом случае новая таблица будет иметь внешний ключ, идентичный первичному ключу таблицы. Например, связь "один к одному" между таблицами на рис. 1.14.
Рис. 1.14. Взаимосвязь "один к одному" между таблицами "Текущие проекты" (PROJECT_CUR) и "Архивные проекты" (PROJECT_OLD)
Если определено каскадное правило удаления для этого внешнего ключа (см. лекцию 8), то СУБД будет автоматически удалять строки новой таблицы, когда соответствующая строка исходной таблицы будет удалена, хотя управление вставкой строк придется перенести в приложение ХД.
При принятии решения о разбиении таблицы следует придерживаться следующего алгоритма:
определить, какие колонки исходной таблицы в какие новые таблицы будут перемещены;
создать новые таблицы с первичным ключом, идентичным первичному ключу исходной таблицы;
если СУБД будет управлять декларативной ссылочной целостностью для новых таблиц таким же образом, как и для исходной таблицы, в случае если она является дочерней таблицей во взаимосвязи, следует добавить колонку внешнего ключа каждой родительской таблицы во взаимосвязи в новую таблицу, т.е. новая таблица должна содержать ограничение внешнего ключа, идентичное родительской таблице, для каждой взаимосвязи. Альтернативой этому решению является создание связи "один к одному" между новой таблицей и исходной таблицей, определение внешнего ключа обратно к исходной таблице тождественным первичному ключу;
если СУБД будет управлять ссылочной целостностью для новых таблиц таким же образом, как и для исходной таблицы, в случае если она является родительской таблицей во взаимосвязи, то следует добавить внешний ключ в каждую дочернюю таблицу исходной таблицы, чтобы идентифицировать эту новую таблицу как дочернюю. Можно так же поступить, как в первой части предыдущего пункта, при этом новые таблицы не следует объявлять как родительские в других взаимоотношениях. Исходная таблица поддерживает все взаимосвязи, в которых она выступает родителем;
следует прописать для разработчиков приложений все команды INSERT для полученных в результате разбиения таблиц или указать правила, которым должна следовать вставка строк в эти таблицы;
следует изменить все представления, которые основывались на исходной таблице, и, если нужно, рассмотреть создание новых представлений для доступа к новым таблицам.
Объединение таблиц базы данных
Объединение таблиц (Table collapsing) является процессом перемещения строк нескольких таблиц в одну, новую таблицу для ограничения числа соединений таблиц БД и улучшения производительности запросов.
Объединяющая таблица включает в себя колонки всех объединяемых таблиц. Если между таблицами были установлены ограничения ссылочной целостности, то при объединении колонки родительской таблицы дублируются, ограничения внешнего ключа таблиц-потомков удаляются из объединяющей таблицы и колонки, участвующие в соединении объединяемых таблиц, удаляются.
Рассмотрим примеры.
Пример 1.4.
Предположим, что было принято решение об объединении таблиц "Покупатель" (Customer) и "Заказ" (Order), — их необходимо объединить, чтобы исключить операцию соединения в запросах к этим таблицам. Физическая модель данных до объединения приведена на рис. 1.15.
Рис. 1.15. Таблицы "Покупатель" (Customer) и "Заказ" (Order) до их объединения
В результате объединения таблиц будет создана одна таблица "Покупатель Счет" (Cust_Order), содержащая все колонки объединяемых таблиц (рис. 1.16).
Рис. 1.16. Таблица "Покупатель Счет" (Cust_Order), объединяющая таблицы "Покупатель" (Customer) и "Заказ" (Order)
Для ХД целесообразно рассматривать объединение нормализованных таблиц иерархии — например, таблиц измерений, представляющих измерение "Время" (Time), как на рис. 1.17 таблица измерений для иерархии "Время" приведена на рис. 1.18.
Рис. 1.17. Иерархия таблиц измерения "Время"
Рис. 1.18. Денормализованная таблица иерархии "Время"
Денормализация колонок
Денормализация колонок (Column denormalization) является процессом для ограничения числа часто встречающихся соединений таблиц БД и улучшения производительности запросов.
Рассмотрим следующий пример.
Пример 1.5.
Пусть задана физическая модель данных (рис. 1.9).
Рис. 1.19. Таблицы физической модели данных
Допустим, что в отчете необходимо напечатать колонки "Название отдела" (Div_name) на платежной расписке из таблицы "Платежная расписка" (Pay Slip) каждого служащего. Для решения этой задачи можно рассмотреть вопрос оденормализации колонок таблицы, чтобы иметь колонку "Название отдела" (Div_Name) в таблице "Платежная расписка" (PaySlip). Перенесем для этого колонку "Название отдела" (Div_Name) ( нисходящая денормализация ) в таблицу "Платежная расписка" (Pay Slip). Физическая модель данных таблицы "Платежная расписка" (Pay Slip) приведена на рис. 19.20.
Рис. 1.20. Нисходящая денормализация таблицы "Платежная расписка" (Pay Slip)
Таким образом, мы сократим число соединений при совместном использовании в отчетах колонок таблицы "Платежная расписка" (Pay Slip) и колонки "Название отдела" (Div_Name).
