Что-то никакой активности
. Либо у всех справочники небольшие, либо УРБД никто не пользует. В общем в моем случае пока остановился на следующем:
Во-первых, немного изменил триггер, который срабатывает на добавление элемента:
WHILE @ParentID != $ПустойИД
BEGIN
INSERT INTO "+ИмяТаблицыДерева+" (ID, ParentID) VALUES (@ID, @ParentID)
Set @ParentID = (SELECT ParentID FROM "+ИмяТаблицы+" WHERE ID = @ParentID)
Set @ParentID = IsNull(@ParentID,$ПустойИД)
END
If @ParentID != $ПустойИД
BEGIN
INSERT INTO "+ИмяТаблицыДерева+" (ID, ParentID) VALUES (@ID, @ParentID)
END
If @IsFolder = 1
BEGIN
--для свежедобавленной группы проверим, может уже есть элементы ей принадлежащие?
--(такое м.б. во время обмена УРБД). В этом случае лучше потом перестроить все дерево (сделаем себе "заметку")
If Exists (Select id From "+ИмяТаблицы+" WHERE ParentID = @ID)
BEGIN
INSERT INTO "+ИмяТаблицыДерева+" (ID, ParentID) VALUES ($ПустойИД, $ПустойИД)
END
END
Как видно, добавилась проверка в цикле что найденный элемент не NULL и если для добавляемой группы найдена ссылка на нее, то добавляем в таблицу "сигнальную" строку с пустыми идами, которая говорит нам что надо бы все "дерево" перестроить.
Затем, н.р. в ПриНачалеРаботыСистемы смотрим, если такой элемент есть, то обновим все дерево. Н.р. вот таким запросом:
Set NoCount On
Declare @Count int
truncate table "+ИмяТаблицыДерева+"
--убираем индексы, чтобы сократить время добавления записей в таблицу
IF EXISTS (SELECT name FROM sysindexes WHERE name = 'IX_Дерево_"+ВидСправочника+"_ID')
DROP INDEX "+ИмяТаблицыДерева+".IX_Дерево_"+ВидСправочника+"_ID
IF EXISTS (SELECT name FROM sysindexes WHERE name = 'IX_Дерево_"+ВидСправочника+"_ParentID')
DROP INDEX "+ИмяТаблицыДерева+".IX_Дерево_"+ВидСправочника+"_ParentID
--выбираем все группы и рассчитаем с помощью функции их уровни
Select id, parentid as parent, dbo.fn_Уровень_"+ВидСправочника+"(id) level
Into "+времтаб+"
From "+ИмяТаблицы+" (NoLock) Where IsFolder = 1
insert into "+времтаб+" (id,parent,level) values ($ПустойИД,$ПустойИД,0)
Create index IX1 on "+времтаб+" (id)
Create index IX2 on "+времтаб+" (level)
Set @Count = (Select Max(level) From "+времтаб+")
--добавляем 'детей' последнего уровня
Insert Into "+ИмяТаблицыДерева+"
Select id, parentid From "+ИмяТаблицы+" (NoLock) where parentid in
(Select id from "+времтаб+" where level = @count)
While @Count > 0
Begin
--добавляем 'внуков', 'правнуков' и т.д. для родителей текущего уровня
Insert Into "+ИмяТаблицыДерева+"
Select dt.id, wr.parent
From "+ИмяТаблицыДерева+" dt (NoLock)
Inner Join "+времтаб+" wr on wr.id = dt.parentid and wr.level = @count
--добавляем элементы и группы этого уровня (всех подчиненных для верхнего уровня)
Insert Into "+ИмяТаблицыДерева+"
Select id, parentid From "+ИмяТаблицы+" (NoLock) where parentid in
(Select id from "+времтаб+" where level = @count-1)
Set @Count = @Count - 1
End
--восстановим индексы
CREATE INDEX [IX_Дерево_"+ВидСправочника+"_ID] ON [dbo].[Дерево_"+ВидСправочника+"]([ID]) ON [PRIMARY]
CREATE INDEX [IX_Дерево_"+ВидСправочника+"_ParentID] ON [dbo].[Дерево_"+ВидСправочника+"]([ParentID]) ON [PRIMARY]
Drop table "+времтаб+"
функция для получения уровня группы:
CREATE FUNCTION dbo."+ИмяФункции+" (@id char(9))
RETURNS tinyint
BEGIN
Declare @lev tinyint, @parent char(9)
Set @parent = @id
Set @lev = 0
while @parent != $ПустойИД
Begin
Select @parent = ParentId From "+ИмяТаблицы+" Where id = @parent
Set @lev = @lev + 1
End
return @lev
END
На тестовой базе и обычной машине в качестве сервера, перезаполнение всей таблички занимает около 2 секунд при ~70 тыс. элементах в справочнике