Алгоритм пересечения глобалов в Caché

Часто возникает задача пересечения подузлов двух глобалов, например, при выполнении поиска вида (Поле1=Значение1)AND(Поле2=Значение2) при использовании своего хранения.

Самый простой вариант – это проход по узлам одного глобала и определение есть ли такой узел во втором глобале. Например:

AND(Buf1,Buf2,ResultBuf) public
{
	Kill @ResultBuf
	Set index=""
	For {
	 	Set index=$Order(@Buf1@(index))
		If index="" Quit
		If $Data(@Buf2@(index)) {
	 		Set @ResultBuf@(index)=""
	 	}	
	}
}

При таком подходе скорость выполнения будет зависеть от числа узлов в глобале, по которому идет цикл. Если в первом глобале будет 1 000 000 записей, а во втором 10, то будет перебираться весь миллион узлов. Гораздо быстрее осуществить поиск по глобалу в котором меньшее число, записей. Но во-первых, не всегда хранится число подузлов в узле, и следовательно нельзя определить в каком из них меньше узлов. Во-вторых, придется все равно выполнить число итераций равное меньшему из двух количеств (при этом число узлов, которые есть в обоих глобалах может быть значительно меньше любого из них).

Рекомендуется в цикле проходить не по одному, а по двум глобалам сразу. Например:

AND(Buf1,Buf2,ResultBuf) public
{
	Kill @ResultBuf
	Set index=""
	For {
	 	Set index=$Order(@Buf1@(index))
		If index="" Quit
		If $Data(@Buf2@(index)) Set @ResultBuf@(index)=""
		Set index=$Order(@Buf2@(index))
		If index="" Quit
		If $Data(@Buf1@(index)) Set @ResultBuf@(index)=""
	}
}

Алгоритм можно расширить и на большее число пересекаемых глобалов.