Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Перестроение индексов: когда это необходимо? / 7 сообщений из 7, страница 1 из 1
24.09.2009, 06:15
    #36213916
kolesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перестроение индексов: когда это необходимо?
Мы сейчас используем такой механизм: при сборке версии удаляются и заново строятся все индексы.
Есть желание при каждой сборке сохранять список построенных индексов и при следующей сборке перестраивать только измененные индексы, и создавать только вновь созданные в описании классов.

Есть два вопроса:

1. Сталкивался ли кто-то с необходимостью перестроения индекса на работающей системе (классы не изменялись)? Когда может возникнуть такая необходимость?

2. Как можно обойти проблему построения индексов при наследовании? При удалении индексов предков удаляются индексы потомков. Собственно поэтомы мы вынуждены вначале удалять все индексы, а потом все строить заново.
...
Рейтинг: 0 / 0
24.09.2009, 07:55
    #36213956
Ptn
Ptn
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перестроение индексов: когда это необходимо?
1. Если нарушена целостность базы, кто-то неудачно покопался в глобале руками например.

2. В наследуемых классах (прямые наследники) индексы не должны пересекаться по именам среди ВСЕХ потомков.

2.1 Однако выложу я прогу одну что ли. AS IS
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
RBIndex
	q
Class(cls)
	new super,arr,rs,refs
	set super=$$GetSuperClass(cls)
	do IndForClass(super,.refs)
	set cls=""
	for  { set cls=$o(refs(cls), 1 ,super) quit:cls=""
		if $e(super, 1 , 1 )="%" {set arr(cls)= 1 }
		else {
			set rs=""""_cls_""""
			d findpath(cls,.rs)
			set @("arr("_rs_")")= 1 
		}
	}
	#; индексы перестраиваем в обратном порядке
	#; из-за наследования - сначала дети потом родители
	#; но если у детей индексы с одинаковым именем ...
	#; тады ..опа..
	set cls="arr",rs= 0 
	set cls="arr("""_$o(arr(""),- 1 )_""")"
	set cls=$q(arr(""),- 1 )
	set:cls'="" cls=$e(cls,1,$l(cls)-1)_",1)"
	if cls'="" {
		for  {	set cls=$q(@cls,- 1 ) quit:cls=""  
			set rs=$qs(cls,$ql(cls))
			w rs,$j(" ", 50 -$l(rs))," "
			d Build($qs(cls,$ql(cls)))
			w !
		}
	}
	q 
All()
	new rs,refs,super
	set rs=##class(%ResultSet).%New("%Dictionary.ClassDefinitionQuery:Summary")
	if rs.Execute() {
		while rs.Next() {  continue:$e(rs.Get("Name"), 1 , 1 )="%"  
			if rs.Get("Persistent")= 1  { 
				set super=$$GetSuperClass(rs.Get("Name"))
				set refs(super)= 1 
			}
		}
	}
	do rs.Close() set rs=""
	set super="" for { set super=$o(refs(super)) quit:super=""  
		do Class(super)
	}
	q
IndForClass(classname,&ret)
	new rs,cls,super,arr,refs,rsind,obj
	/// Для потомков
	set rs=##class(%ResultSet).%New("%Dictionary.ClassDefinitionQuery:SubclassOf")
	if rs.Execute(classname,"%") {
		while rs.Next() {
			set cls=rs.Get("Name") 
			continue:$e(cls, 1 , 1 )="%"  
			set rsind=##class(%ResultSet).%New("%Dictionary.CompiledIndexQuery:Summary")
			if rsind.Execute(cls) {
				while rsind.Next() {
					
					set obj=##class(%Dictionary.CompiledIndex).%OpenId(cls_"||"_rsind.Get("Name"), 0 )
					if obj'="" {
						if obj.IdKey'= 1  {
							set super=$$GetSuperProperty(cls)
							set refs(cls)=$p(super,",", 1 )
						}
					}
					set obj=""
					quit:$d(refs(cls))  
				}
			}
			set rsind=""
		}
	}
	do rs.Close() set rs=""
	/// для себя самого
	set rsind=##class(%ResultSet).%New("%Dictionary.CompiledIndexQuery:Summary")
	if rsind.Execute(classname) {
		while rsind.Next() {
			
			set obj=##class(%Dictionary.CompiledIndex).%OpenId(classname_"||"_rsind.Get("Name"), 0 )
			if obj'="" {
				if obj.IdKey'= 1  {
					set super=$$GetSuperProperty(classname)
					set refs(classname)=$p(super,",", 1 )
				}
			}
			set obj=""
			quit:$d(refs(classname))  
		}
	}
	do rsind.Close() set rsind=""
	merge ret=refs
	quit 
findpath(class,result) quit:$g(class)=""  quit:$d(refs(class))= 0   
	if $e($g(refs(class)), 1 , 1 )'="%" { set result=""""_$g(refs(class))_""","_result d findpath($g(refs(class)),.result)}
	quit 
Build(cls) new ret
	set $ZT="BuildErr"
	set ret=1
	TS
	w ">"
	if ##class(%Dictionary.CompiledClass).%ExistsId(cls) {
		set ret=$zobjclassmethod(cls,"%PurgeIndices")
		set:ret=1 ret=$zobjclassmethod(cls,"%BuildIndices")	
	}else {
		w " not compiled ?"
	}
	set $ZT=""
	if ret=1 {TC  w "OK"}
	else  {TRO  w "OK"}
	q  
BuildErr
	set $ZT="" TRO  
	w " Ошибка: ",$ZE," ",cls,!
	q  
GetSuperClass(cls)
	new ret,isend,sp
	set ret=cls,isend=0
	set sp=$$GetSuperProperty(cls)	
	if $e(sp)="%" {set isend=1 }
	set cls=$p(sp,",",1)
	quit:isend'= 1  $$GetSuperClass(cls)
	quit ret
GetSuperProperty(cls)
	new obj,ret
	set ret=""
	s obj=##class(%Dictionary.ClassDefinition).%OpenId(cls, 0 )
	if obj'="" { set ret=obj.Super do obj.%Close() }
	set obj=""
	quit ret
Перестройка индексов одного класса с потомками
d Class^RBIndex(<имя класса>)

Перестройка индексов для всей области
d All^RBIndex()
...
Рейтинг: 0 / 0
04.02.2010, 11:36
    #36449013
kolesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перестроение индексов: когда это необходимо?
Ptn,

Спасибо. Но осталась одна проблема:
Как перестроить только измененные индексы?
И она возвращает к старому вопросу: как получить текстовый слепок объекта. В данном случае - хранящегося в базе описания индекса...

Неужели без использования перебора по подузлам ^oddDEF("xClass","i","yIndex") не обойтись?
...
Рейтинг: 0 / 0
04.02.2010, 16:24
    #36450082
Блок А.Н.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перестроение индексов: когда это необходимо?
Вы имеете в виду, что в определении класса изменилось определение индекса, и нужно перестроить именно эти индексы?
У нас программисты при выкладывании обновления пишут текстовку к каждому классу, в момент выгрузки файла на диск, и пишут что изменилось в классе и что нужно сделать при его накатывании, в том числе перестройки индексов, запуск каких-то процедур и т.д.

Или вы имеете в виду, что у части записей таблицы имеются кривые индексы и нужно именно их найти и перестроить?
Я как-то занимался этой проблемой, мне в стандартной перестройке индексов не понравилось, что сначала грохаем все записи индексов, а потом медленно их строим, при этом фактически работу пользователей приходится блокировать, либо перестраиваем индексы без удаления предыдущих, но тогда имеем риск оставить кривые индексные записи.
Моя программа перебирала записи таблицы по одной и проверяла индексы для нее, потом проверяла все индексные записи и удаляла неправильные, при этом работоспособность системы не нарушалась.
К сожалению, работала она примерно в 5-10 раз медленней стандартной, понимала не все виды индексов и вообще мне было страшно ее использовать :-). В итоге потом отказался.
...
Рейтинг: 0 / 0
05.02.2010, 04:24
    #36450942
kolesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перестроение индексов: когда это необходимо?
Блок А.Н.,

Речь идет об автоматическом процессе сборки версии (у нас это делается 1-2 раза в неделю)
Так сама сборка классов идет минут 15-ть, а вот перестроение индексов уже минут 25-ть... и это - не предел ;)

Комментарии при чекине не особо спасут - их придется парсить, и вероятность ошибки в таком комментарии велика. Да и программер может забыть о чем-то ;)
...
Рейтинг: 0 / 0
06.02.2010, 09:59
    #36453242
kolesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перестроение индексов: когда это необходимо?
Ptn2. В наследуемых классах (прямые наследники) индексы не должны пересекаться по именам среди ВСЕХ потомков.

Попробовал воспроизвести - не компилируется такая ситуация в 2009.1 - говорит, что такой индекс уже занят другим наследником.
Также не компилируются переопределенные индексы. (если в следующем далее примере в классе а.В переопределить индекс (вот так: Index NameIndex On Name [ Data = Age ];) то класс перестает компилиться с ошибкой в духе "невозможно переопределить определение Index".

Ptn
#; индексы перестраиваем в обратном порядке
#; из-за наследования - сначала дети потом родители

Позволим себе небольшой эксперимент:
Возьмем 3 класса:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
Class a.A Extends (%Persistent, %Populate)
{

Property Name As %String;

Index NameIndex On Name;

}
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
Class a.B Extends a.A
{

Property Age As %Integer;

Index AgeIndex On Age;

}
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
Class a.C Extends a.A
{

Property DogAge As %Integer;

Index DogAgeIndex On DogAge;

}
Выполним
>d ##class(a.A).Populate(5)
>d ##class(a.B).Populate(5)
>d ##class(a.C).Populate(5)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
 1 :  ^a.AI("AgeIndex", 66790836 , 8 ) = "~a.B~" 
 2 :  ^a.AI("AgeIndex", 428408320 , 7 ) = "~a.B~" 
 3 :  ^a.AI("AgeIndex", 615925956 , 9 ) = "~a.B~" 
 4 :  ^a.AI("AgeIndex", 647579749 , 10 ) = "~a.B~" 
 5 :  ^a.AI("AgeIndex", 883157847 , 6 ) = "~a.B~" 
 6 :  ^a.AI("DogAgeIndex", 349144970 , 11 ) = "~a.C~" 
 7 :  ^a.AI("DogAgeIndex", 408282601 , 15 ) = "~a.C~" 
 8 :  ^a.AI("DogAgeIndex", 475077891 , 13 ) = "~a.C~" 
 9 :  ^a.AI("DogAgeIndex", 935942734 , 12 ) = "~a.C~" 
 10 :  ^a.AI("DogAgeIndex", 946521295 , 14 ) = "~a.C~" 
 11 :  ^a.AI("NameIndex"," ALTON,VALERY P.", 14 ) = "~a.C~" 
 12 :  ^a.AI("NameIndex"," CHESIRE,IMELDA B.", 3 ) = "" 
 13 :  ^a.AI("NameIndex"," DUQUESNOY,SAM T.", 13 ) = "~a.C~" 
 14 :  ^a.AI("NameIndex"," ENO,ASHLEY V.", 4 ) = "" 
 15 :  ^a.AI("NameIndex"," FAUST,YAN I.", 1 ) = "" 
 16 :  ^a.AI("NameIndex"," FRITH,WOLFGANG D.", 9 ) = "~a.B~" 
 17 :  ^a.AI("NameIndex"," GIBBS,TERRY J.", 8 ) = "~a.B~" 
 18 :  ^a.AI("NameIndex"," JOHNSON,LAURA R.", 7 ) = "~a.B~" 
 19 :  ^a.AI("NameIndex"," KELVIN,KEVIN P.", 2 ) = "" 
 20 :  ^a.AI("NameIndex"," KLEIN,YAN L.", 12 ) = "~a.C~" 
 21 :  ^a.AI("NameIndex"," KOENIG,CHRISTINE S.", 10 ) = "~a.B~" 
 22 :  ^a.AI("NameIndex"," NOVELLO,VALERY I.", 5 ) = "" 
 23 :  ^a.AI("NameIndex"," RAGON,DAN Q.", 15 ) = "~a.C~" 
 24 :  ^a.AI("NameIndex"," RAMSAY,WILLIAM E.", 6 ) = "~a.B~" 
 25 :  ^a.AI("NameIndex"," XENIA,NORBERT V.", 11 ) = "~a.C~" 
Далее выполняем d ##class(a.C).%PurgeIndices() - удаляется только ^a.AI("DogAgeIndex"), а ^a.AI("NameIndex") остается нетронутым(!).
Сделаем еще хуже - поправим ручками глобаль.
Было
Код: plaintext
^a.AD( 12 ) = $lb("~a.C~","Klein,Yan L.")
Стало
Код: plaintext
^a.AD( 12 ) = $lb("~a.C~","Vasya Pupkin Jr.")
Выполняем
>d ##class(a.C).%BuildIndices(,1)
И смотрим, что получилось:
Код: plaintext
^a.AI("NameIndex"," KLEIN,YAN L.", 12 ) = "~a.C~" 

Очевидно, не врет документация, когда говорит:
ИСBeginning with version 2009.1, %PurgeIndices validates the name of the indices it is passed. If the index does not originate in the current class then it cannot be purged.
Note:
There is an exception to this rule; if the current class is the extent root class and the index is inherited or originates here, it is valid for building and purging.


Заходим с тыла:
...
Рейтинг: 0 / 0
06.02.2010, 10:07
    #36453244
kolesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перестроение индексов: когда это необходимо?
>d ##class(a.A).%PurgeIndices()

Удалились все индексы NameIndex (для всех 3-х классов)

>d ##class(a.A).%BuildIndices()

Все нормально. В т.ч. и Вася Пупкин ;)

Можно сделать вывод:
Начиная с 2009.1 индекс - штука, гораздо более отвязанная от классов, наследования и проч., чем индекс в более ранних версиях.

Соответственно, пройдя запросом
Код: plaintext
SELECT Id,Name,parent->Name Class FROM %Dictionary.CompiledIndex where parent->System =  0  and SystemAssigned =  0 
и просто вызвав перестроение измененных индексов, получим нужный результат.

Еще один вывод: ИС о нас думает!

Пошел править программу сборки...
...
Рейтинг: 0 / 0
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Перестроение индексов: когда это необходимо? / 7 сообщений из 7, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]