![]() |
|
сделать стартовой | добавить в избранное |
![]() |
Иерархические справочники с линейным временем доступа |
Глеб Земсков Введение Разработка иерархических справочников – достаточно часто встречающаяся задача в бизнес-приложениях. Существует достаточно много алгоритмов хранения дерева в реляционных СУБД. В данной статье будет рассказано об одной из таких моделей. Ее достоинства – простота реализации, быстрота выборки и добавления нового элемента, а среди недостатков можно выделить относительную сложность вставки и перемещения данных, а также конечную глубину иерархии. Но те или иные недостатки имеются в любой схеме хранения иерархических данных в РСУБД. Насколько хорош алгоритм Для иерархических справочников мы определим несколько наиболее часто встречающихся задач, которые затрагивают иерархию. получение всех потомков узла; получение непосредственных потомков узла; добавление потомка; удаление узла с потомками; перенос узла. Иерархия Дьюи (Dewey) Иерархический справочник может быть основан на алгоритме записи, используемом в системе десятичной классификации Дьюи (Dewey Decimal Classifica io ). Нас в данный момент интересует не сам классификатор, а используемый в нем принцип. Попробую его описать. Каждый узел содержит некоторый идентификатор, уникальный среди потомков его родителя. Каждый узел содержит путь от корневого элемента к данному. Путь реализуется с помощью идентификаторов, разделенных символом точки. Например: 1 Организация «Рога и копыта». 1.1 Департамент «Рога». 1.1.1 Отдел продажи рогов. 1.1.2 Отдел покупки рогов. 1.1.2.1 Группа оценки качества рогов. 1.1.3 Отдел проката рогов. 1.2. Департамент «Копыта» 1.2.1 Отдел покупки копыт. 1.2.2 Отдел продажи копыт. Как можно сразу заметить, при работе с подобным классификатором удобно использовать оператор LIKE. Если указывается путь, в котором начальные символы не являются маской, база данных может использовать индекс с операцией i dex sca с диапазонным поиском. Создадим тестовый пример. CREA E ABLE DEPAR ME ( ID I PRIMARY KEY IDE I Y(1,1), Pa h VARCHAR(180) U IQUE, Posi io I O ULL, AME VARCHAR(128) ) GO I SER I O DEPAR ME (Pa h, Posi io , AME) VALUES ('1', 1, 'Организация «Рога и копыта»') I SER I O DEPAR ME (Pa h, Posi io , AME) VALUES ('1.1', 1, 'Департамент «Рога»') I SER I O DEPAR ME (Pa h, Posi io , AME) VALUES ('1.1.1', 1, 'Отдел продажи рогов') I SER I O DEPAR ME (Pa h, Posi io , AME) VALUES ('1.1.2', 2, 'Отдел покупки рогов') I SER I O DEPAR ME (Pa h, Posi io , AME) VALUES ('1.1.2.1', 1, 'Группа оценки качества рогов') I SER I O DEPAR ME (Pa h, Posi io , AME) VALUES ('1.1.3', 3, 'Отдел проката рогов') I SER I O DEPAR ME (Pa h, Posi io , AME) VALUES ('1.2', 2, 'Департамент «Копыта»') I SER I O DEPAR ME (Pa h, Posi io , AME) VALUES ('1.2.1', 1, 'Отдел покупки копыт') I SER I O DEPAR ME (Pa h, Posi io , AME) VALUES ('1.2.2', 2, 'Отдел продажи копыт') GO Расчет длины поля Pa h Прежде всего следует уточнить, почему поле Pa h имеет длину 180. Расчет прост. Количество подчиненных отделов каждого узла в справочнике вряд ли может быть больше, чем трехзначная цифра (от 0 до 999 подразделений). Такое не под силу даже таким гигантам, как Газпром. Делим количество занятых символов 4 (учитывая точку) и получаем уровень возможных вложений – 60.
Цифра также запредельная. Можно подойти с другой стороны. Уровень вложений вряд ли будет больше 20. Делим 180 на 20, и получаем 9 символов. 8 символов (учитывая точку) в десятичной системе – это десять миллионов подразделений. Таким образом, 180 символов в данном случае достаточно, чтобы описать избыточное число организаций и отделов, но недостаточно, чтобы размер сильно влиял на производительность базы данных. И это при том, что мы рассчитывали самые плохие случаи. В действительности, вместимость иерархии значительно больше. Если количество данных больше, то размер Pa h можно увеличить. Но для данного справочника его размера достаточно. И этого размера хватало для большинства бизнес-приложений, с которыми я встречался. Получение всех потомков узла. Допустим, мы собираемся получить все подразделения, входящие в отдел «Рога и Копыта». С помощью Pa h родителя создаем простой запрос. SELEC FROM DEPAR ME WHERE Pa h LIKE '1.1.%' Добавив к условию в операторе LIKE, мы указали запросу выбрать все записи, имеющие Pa h длиннее, чем у родителей. Такой запрос также может быть построен относительно данных родительского узла. SELEC resul . FROM DEPAR ME pare I ER JOI DEPAR ME resul O (resul .Pa h LIKE pare .Pa h '.%') WHERE pare . AME = 'Департамент «Рога»' Получение непосредственных потомков узла Возьмем предыдущий запрос и добавим отрицательное условие для непосредственных потомков данного Pa h. SELEC FROM DEPAR ME WHERE Pa h LIKE '1.1.%' A D Pa h O LIKE '1.1.%.%' В результате мы получим все подчиненные элементы от узла “Департамент «Рога»”. Можно выбрать сразу несколько уровней: SELEC FROM DEPAR ME WHERE Pa h LIKE '1.1.%' A D Pa h O LIKE '1.1.%.%.%' Добавление потомков. В данном случае нам нужно вставить запись по определенному пути с уникальным идентификатором Posi io . Создадим подчиненный элемент узла со значением Pa h 1.1. Уникальность идентификатора важна только для самих потомков. Поэтому вычислим максимальное значение для потомков данного родителя и прибавим к нему единицу. Если на клиенте известны соседние элементы, и можно получить идентификатор Posi io сразу, то запрос не представляет сложности: I SER I O DEPAR ME (Pa h, Posi io , AME) VALUES ('1.1.4', 4, 'Отдел проката копыт') Если Posi io неизвестен, то можно получить его в запросе: I SER I O DEPAR ME (Pa h, Posi io , AME) SELEC '1.1' '.' IS ULL(CAS (MAX(Posi io ) 1 AS VARCHAR), '1'), IS ULL(MAX(Posi io ) 1, 1), 'Отдел проката копыт' FROM DEPAR ME WHERE Pa h LIKE '1.1.%' A D Pa h O LIKE '1.1.%.%' ПРЕДУПРЕЖДЕНИЕ В многопользовательской среде, для некоторых баз данных, таких, как MSSQL, подобное добавление является классическим случаем фантома. Чтобы преодолеть данную проблему, можно повысить уровень транзакции до Serializable, использовать в качестве поля Posi io автоинкрементальное поле или просто учитывать, что можно получить ошибку при вставке одинаковых значений в уникальный индекс поля Pa h. Удаление узла с потомками Удаление похоже на операцию выборки за исключением того, что мы также должны удалить текущий узел: DELE E FROM DEPAR ME WHERE Pa h LIKE '1.1%' С помощью дополнительной точки в аргументе оператора LIKE можно удалить все дочерние элементы без родительского узла: DELE E FROM DEPAR ME WHERE Pa h LIKE '1.1
.%' Имеет смысл построить триггер, который будет автоматически удалять дочерние элементы: CREA E RIGGER DELE E ODES R O DEPAR ME AF ER DELE E AS DECLARE @Pare Pa h VARCHAR(180) BEGI SELEC @Pare Pa h=Pa h FROM dele ed DELE E FROM DEPAR ME WHERE Pa h LIKE @Pare Pa h '.%' E D В этом случае можно гарантировать, что узел будет удаляться вместе с дочерними элементами, и команда удаления еще более упростится. DELE E FROM DEPAR ME WHERE Pa h='1.1' Перенос узла Перенос узла – более сложная операция, чем предыдущая. Для нее нужно будет выполнить две команды обновления. Например, перенесем узел с Pa h 1.1, сделав его дочерним узлом по отношению к узлу 1.2. Первой командой мы перенесем сам узел: UPDA E DEPAR ME SE Pa h = (SELEC '1.2.' IS ULL(CAS (MAX(D.Posi io ) 1 AS VARCHAR), '1') FROM DEPAR ME D WHERE D.Pa h LIKE '1.2.%' A D D.Pa h O LIKE '1.2.%.%'), Posi io = (SELEC IS ULL(MAX(D.Posi io ) 1, '1') FROM DEPAR ME D WHERE D.Pa h LIKE '1.2.%' A D D.Pa h O LIKE '1.2.%.%') WHERE Pa h = '1.1' Второй командой мы обновим все идентификаторы Pa h для дочерних элементов: UPDA E DEPAR ME SE Pa h=S UFF(Pa h, 1, 3, '1.2.4') WHERE Pa h LIKE '1.1.%' Так же, как и в случае с удалением, мы можем построить триггер, который будет гарантированно адаптировать дочерние ссылки, а также следить за правильностью поля Posi io : CREA E RIGGER UPDA E ODES R O DEPAR ME AF ER UPDA E AS DECLARE @OldPare Pa h VARCHAR(180), @ ewPare Pa h VARCHAR(180), @Pare Posi io I , @RealPare Posi io I BEGI IF UPDA E(Pa h) BEGI SELEC @OldPare Pa h = Pa h FROM dele ed SELEC @ ewPare Pa h = Pa h, @Pare Posi io = Posi io FROM i ser ed -- если поле Posi io некорректно, то обновляем его согласно Pa h SELEC @RealPare Posi io = CAS (RIGH (@ ewPare Pa h, CHARI DEX('.', REVERSE(@ ewPare Pa h)) - 1) AS I ) IF (@RealPare Posi io &l ;> @Pare Posi io ) UPDA E DEPAR ME SE Posi io = @RealPare Posi io WHERE Pa h = @ ewPare Pa h -- обновляем все дочерние элементы UPDA E DEPAR ME SE Pa h = S UFF(Pa h, 1, LE (@OldPare Pa h), @ ewPare Pa h) WHERE Pa h LIKE @OldPare Pa h '.%' E D E D Некоторые дополнения Одним из полезных свойств данного алгоритма является возможность сортировать данные согласно иерархии. Это очень полезное и часто используемое свойство. Если достаточно часты обращения согласно иерархии, и если позволяет используемая СУБД, стоит хранить таблицу в состоянии, сортированном по полю Pa h. Если вы хотите сортировать последовательность непосредственно подчиненных элементов, то можно ввести дополнительную цифру, в которой будет лежать количество цифр в элементе. Например, для Posi io c номером 2 идентификатор в Pa h будет равен 12, где 1 – количество символов в идентификаторе. А если Posi io равен 12, то идентификатор будет равен 212. В этом случае сортировка строковых данных будет совпадать с последовательностью числовых, и мы получим полностью сортированный Pa h. Гораздо хуже обстоит дело, если нужно реализовать операцию вставки. Если адаптировать все Pa h на подчиненные и соседние узлы.
Эти личности также оказывают давление на преступных военных лидеров, заставляя их раскрывать больше информации о том, что действительно происходит в космическом пространстве. В научных кругах есть люди, чьи предположения относительно истинных целей нынешнего военного и научного исследования лунной и марсианской поверхности, абсолютно точны. Благодаря их проницательности, решительности и упрямству вы наконец получаете доступ к правде о различных проявлениях и формах жизни на других планетах, существовавших в конструкции линейного времени из прошлого и будущего, но в то же время являющихся частью вневременного бытия, как вы узнаете сейчас. Мы следим за первопроходцем Ричардом Хоуглендом, изучающим доказательства, которые подтверждают неопубликованные данные о космических открытиях НАСА. Он несет вам первые частицы информации, свидетельствующие о том, что на красной планете и Луне ранее существовала жизнь. Вы, искатели знания, тянетесь к этой информации, чтобы в своих поисках недостающего звена заполнить пустоту своей галактической памяти
1. Концепции иерархической Вселенной по Лапласу
2. Чрезвычайные ситуации мирного времени
3. Л.А.Кацва "История России с Древних Времен и до ХХ Века"
4. Введение «Временного положения» 1867-1868 гг. и политико-правовые последствия для казахов
5. Пособия по временной нетрудоспособности
9. От средневековья - к "новому времени"
10. Европейская культура нового времени
11. Сексуальные жизнь времен Древних цивилизаций
12. Из двух друзей всегда один раб другого (Лермонтов "Герой Нашего времени")
13. Неужели зло так привлекательно? (по роману Лермонтова "Герой нашего времени")
14. Каким видит Лермонтов героя своего времени в романе "Герой нашего времени"
15. Почему Пьера и князя Андрея можно назвать лучшими людьми их времени
16. Почему повесть "Княжна Мэри" занимает центральное место в романе "Герой нашего времени"?
17. Базаров герой своего времени по роману Тургенева "Отцы и дети"
18. Лессинг: «О законах временных и пространственных видов искусств»
19. В.Г. Белинский о романе М.Ю. Лермонтова "Герой нашего времени"
26. Что является CDMA (Разделение Кодекса Многократный Доступ)?
27. Криптографическая защита функционирование ЛВС в реальном режиме времени
28. Защита информации в системах дистанционного обучения с монопольным доступом
29. Защита информации от несанкционированного доступа методом криптопреобразования /ГОСТ/
32. Парольные методы защиты информации в компьютерных системах от несанкционированного доступа
33. Переходные процессы в линейных цепях
34. Лабораторная работа №5 по "Основам теории систем" (Транспортные задачи линейного программирования)
36. Решение систем линейных алгебраических уравнений методом Гаусса и Зейделя
37. Контрольная работа по линейной алгебре
41. Решение задач линейной оптимизации симплекс – методом
42. Итерационные методы решения систем линейных уравнений с неединственными коэффициентами
43. Уголовный закон во времени и в пространстве
44. Уголовное право буржуазных государств новейшего времени
46. Комплексное моделирование электрических и тепловых характеристик линейного стабилизатора напряжений
47. Спектральный анализ и его приложения к обработке сигналов в реальном времени
48. Определение линейных и угловых перемещений параметрическими измерительными преобразователями
49. Расчет времени откачки распределенных вакуумных систем
50. Cкремблирование и дескремблирование линейного сигнала
52. Измерение больших линейных геометрических размеров
53. Пособия по временной нетрудоспособности
57. Физическая природа времени гравитации и материи
59. Этика средневековья и нового времени
60. Философия нового времени (Р. Декарт)
61. Философия Нового времени в работах Ф. Бекона и Р. Декарта
62. Организация рабочего дня руководителя, управление временем
63. Планирование рабочего времени менеджера
64. Методика установления норм времени и определения норм выработки. Нормативы численности
65. Прогнозирование временных рядов
66. Оптимизация объемов производства на краткосрочных временных интервалах
67. Законодательное закрепление свободы совести Временным правительством
68. «Повесть временных лет» о происхождении русского государства
69. Реалии открытого пространства-времени: к пониманию нашей исторической системы
73. Александр македонский портрет на фоне времени
74. Люди и события смутного времени
75. Февральская революция 1917 года. Политика Временного правительства
76. Победоносцев К. П. - критик «великой лжи нашего времени»
78. Военные действия Московского государства в период "Смутного времени" (1604-1610 гг.)
80. Европа а начале нового времени.
81. Россия на окраине Европы. Исторический анализ событий и времен начала 20-го век
83. Лермонтов: Герой нашего времени
85. Скульптурный портрет времени Республики I в. до н.э.
89. Сущность и социальное назначение свободного времени
90. Динамика развития любительского театра в России с 60-х годов до настоящего времени
91. Искусство позднего времени (11 в - 332 г. до н.э.)
92. Древнегреческая «игривая» культура и европейская порнография новейшего времени
94. Федот Кадушкин — трагическая фигура своего времени (по роману И. Акулова «Касьян Остудный»)
95. Литература Смутного времени
96. Пушкин и литературное движение его времени
97. Пушкин и салонная культура его времени: заметки к теме
98. Пространственно-временная структура романа М. А. Булгакова «Мастер и Маргарита»