- сам по себе VIEW не отличается большим интеллектом.
- если не задан явно PROP:ORDER и не указан перед открытием VIEW используемый ключ, то при построении выборки игнорируются все ключи и выборка строится по порядку записей. Естественно — очень медленно, т.к. необходимо перебирать ВСЕ записи. В этом случае, перед открытием VIEW можно и не ставить операторы SET(View) или SET(File), но НЕОБХОДИМО ставить один из них перед первым NEXT()/PREVIOUS()! Иначе, сами понимаете, не будет инициализирован порядок просмотра выборки.
- если не задан явно PROP:ORDER, но перед открытием VIEW задан ключ просмотра, то именно этот ключ и будет использован при построении выборки. Если ключ не подходит для заданного фильтра, то скорость выборки маленькая. Если задан правильный ключ, то первая и последняя записи выборки будут считаны мгновенно. Скорость самой выборки всего диапазона будет зависеть от ее размера. Но, в любом случае, это будет самый оптимальный вариант. Так что, как видим, VIEW не блещет интеллектом и не выбирает сам подходящий ключ — все делает программист.
- если задан явно PROP:ORDER, то теперь все зависит от того, совпадает ли он с ключом, оптимальным для фильтра. Дело в том, что независимо от того, какой ключ будет задан перед открытием VIEW, выбирается ВСЕГДА самый оптимальный для заданной сортировки. Вот здесь и проявляется интеллектуальность VIEW. Если выбранный ключ является оптимальным и для заданного фильтра, то такая выборка будет самой оптимальной. В противном случае я даже затрудняюсь сказать, какой ключ используется или используется выборка по порядку записей. По крайней мере, автоматом НЕ ВЫБИРАЕТСЯ первый ключ — это точно. В результате проведенных тестов есть подозрение, что в некоторых случаях (разные фильтры) выбирается оптимальный ключ, т.к. в этих случаях время построения выборки с сортировкой меньше времени полного прохода всех записей.
Подводя итог под вышесказанным, можно рекомендовать следующие варианты инициализации VIEW:
не используется PROP:ORDER и не используется PROP:FILTER.
Open(View) Set(View) Loop Next(View); if ErrorCode() then Break. . Close(View)
не используется PROP:ORDER, но используется фильтр.
если нет ключа, оптимального для заданного фильтра:
View{PROP:Filter} = '...'
Open(View)
Set(View)
Loop
Next(View); if ErrorCode() then Break.
.
Close(View)
если есть ключ, оптимальный для заданного фильтра:
View{PROP:Filter} = '...'
Set(FIL:Key)
Open(View)
Set(View) ! желательно использовать
Loop
Next(View); if ErrorCode() then Break.
.
Close(View)
Заметьте, что нет нужды задавать полную форму оператора SET: SET(FIL:Key,FIL:Key).
В данном случае ОБЯЗАТЕЛЬНО надо инициировать поля ключа, которые не указаны в фильтре. Ключевые поля, указанные в фильтре инициируются автоматом. Но в случае многокомпонентного ключа, во избежании недоразумений и глюков, рекомендую ЯВНО инициировать ВСЕ поля ключа. Т.е. самым правильным и гарантированно работающим кодом будет такой код:
View{PROP:Filter} = '...'
Clear(FIL:Record,-1)
FIL:KeyField1 = ...
FIL:KeyField2 = ...
...
Set(FIL:Key)
Open(View)
Set(View) ! желательно использовать
Loop
Next(View); if ErrorCode() then Break.
.
Close(View)
используется PROP:ORDER. В данном случае без разницы — используется фильтр или нет.
View{PROP:Order} = '...'
Open(View)
Set(View)
Loop
Next(View); if ErrorCode() then Break.
.
Close(View)
Так что, правильным кодом для примера, который открыл это обсуждение, будет:
File FILE,PRE(FIL),...
Date_Key KEY(+FIL:Date),DUP,NOCASE
Record RECORD
...
Date DATE
...
END
END
LOC:DateBeg DATE
LOC:DateEnd DATE
CODE
...
Open(File)
BIND(FIL:Record)
BIND('DateBeg',LOC:DateBeg); LOC:DateBeg = DATE(1,1,2001)
BIND('DateEnd',LOC:DateEnd); LOC:DateEnd = DATE(12,31,2001)
View{PROP:Filter} = '(FIL:Date => DateBeg) AND (FIL:Date <= DateEnd)'
Set(FIL:Date_Key)
Open(View)
Set(View) ! желательно использовать
Loop
Next(View); if ErrorCode() then Break.
...
.
Close(View)
Close(File)
...
