On-line: гостей 0. Всего: 0 [подробнее..]
АвторСообщение
постоянный участник




Пост N: 1691
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 26.02.11 14:25. Заголовок: Проблема с условной индексацией 2


Возвращаюсь к этой теме повторно !

Раньше было получено рабочее решение:
условной индексации по БД из 60 000 записей, имеющей 263 поля и занимающей 55 Мб решается так:
nKolRecords := LASTREC()
cIndexTo := "PADL(ALLTRIM(FIELD->CNumKvar),5)"
cFilterTo := "NN==2010490.AND.!DELETED()"
----------------------------------------------------------------------------------
INDEX ON &cIndexTo TAG "ONE" TO ("temp.cdx") ;
EVAL SAY_PROC() ;
EVERY nKolRecords / 10 ;
WHILE &cFilterTo ADDITIVE // замена на FOR &cFilterTo ADDITIVE увеличивает построение индекса на 6 сек.
ORDSETFOCUS( "ONE" )
DBSETORDER(INDEXORD())
DBGOTOP()

где SAY_PROC() - функция рисования бегунка, возвращает всегда .T.

Сейчас потребовалась выборка по дате:

cIndexTo := "DTOS(FIELD->DATEPRIX)+STR(FIELD->TIMEPRIX)"
cFilterTo := "DATEVvod=CTOD("26.02.11).AND.KOPERAT=101.AND.!DELETED()"
---------------------------------------------------------------------------------
INDEX ON &cIndexTo TAG "ONE" TO ("temp.cdx") ;
EVAL SAY_PROC() ;
EVERY nKolRecords / 10 ;
WHILE &cFilterTo ADDITIVE
ORDSETFOCUS( "ONE" )
DBSETORDER(INDEXORD())
DBGOTOP()

Индекс строится мгновенно, но функция FOUND() всегда возвращает .F. - хотя если поставить заместо WHILE ---> FOR то нормально работает, правильно возвращает.
но FOR - строит медленнее... чем WHILE .....

В чем дело, тип ДАТА или ЧИСЛА неправильно в фильтре ??? или еще чего ??? подскажите пожалуйста.


Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 32 , стр: 1 2 All [только новые]


постоянный участник


Пост N: 505
Зарегистрирован: 27.01.07
ссылка на сообщение  Отправлено: 26.02.11 16:20. Заголовок: Выдержка из хэлпа: ..


Выдержка из хэлпа:

 цитата:

FOR <lForCondition>
This is an optional logical expression which is evaluated for all records in the current work area. Those records where <lForCondition> yields .T. (true) are included in the index. The FOR condition is stored in the index file and is maintained by the database driver when records are updated. That is, if a record is changed so that it does not match the FOR condition, it is removed from the index. The FOR expression cannot exceed 250 characters in length. RDDs that do not support a FOR condition when creating indexes generate a runtime error when this option is used.
WHILE <lWhileCondition>
This is a logical expression indicating to continue index creation while the condition is true. The INDEX command stops evaluating records as soon as <lWhileCondition> yields .F. (false). Unlike the FOR expression, which is stored in the index file and exists throughout the lifetime of an index, the WHILE condition is only evaluated during index creation. It is discarded when the index is complete.


Возможно, при использовании WHILE нужные записи просто не попадают в индекс.

Спасибо: 0 
ПрофильЦитата Ответить



Пост N: 11
Зарегистрирован: 19.08.10
ссылка на сообщение  Отправлено: 26.02.11 18:29. Заголовок: По-русски: FOR <..


По-русски:

FOR <lForCondition>

<lForCondition> - необязательное логическое выражение, определяющее условие: FOR условие сохраняется в индексном файле и рассматривается в том случае, когда индексный файл восстанавливается, используя REINDEX. Значения индекса добавляются в индекс только для записей, когда <lForCondition> возвращает значение .T. (истина).



WHILE <lWhileCondition>



<lWhileCondition> - необязательное логическое выражение, определяющее условие: записи копируются в индекс, начинаясь от текущей записи до тех пор, пока <lWhileCondition> возвращает значение .T. (истина). При значении .F. (ложь) действие заканчивается. WHILE условие не сохраняется в индексном файле, рассматривается только в течение выполнения команды INDEX ON и не доступно в течении будущей реорганизации индекса с использованием REINDEX.

Похоже, действительно, нужные записи просто не попадают в индекс. И "индекс строится мгновенно" потому, что при первом же .F. построение заканчивается или указатель был в конце таблицы.

Попробуй на первую запись сперва переместиться:

DBGOTOP()
INDEX ON &cIndexTo TAG "ONE" TO ("temp.cdx") ;
//...


Спасибо: 0 
ПрофильЦитата Ответить
Администратор




Пост N: 1837
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 26.02.11 18:43. Заголовок: Да сам подход неправ..


Да сам подход неправильный. Нельзя так строить индекс. Если для индекса задать условие for, то при создании индекса будут выбраны все записи в файле, но в индекс попадут только те, которые удовлетворяют for. То есть, для построения индекса нужна выборка всех записей файла.
Если задать условие while, то при построении индекса будут выбраны записи до той, которая не удовлетворяет while. Поскольку физически записи могут располагаться произвольно, то, если первая запись не удовлетворяет этому условию, то в индекс не будет включено ни одной. Если вторая - то в индексе будет одна запись. Индекс будет построен мгновенно, но он будет пустой.
Сама идея использовать временный индекс с for или while для разовой выборки порочна. Если использовать for, то для построения индекса необходимо выбрать все записи файла. Но ведь при использовании существующих индексов можно задать условие выборки только части записей.
Использование же while просто бесполезно, правильность индекса зависит от случая. Практически всегда он будет неправильный
Вывод: Андрей, откажись от этих глупостей, и используй традиционный подход.


Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 1692
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 26.02.11 23:47. Заголовок: Chikanuk Спасибо бол..


Chikanuk Спасибо большое за перевод и совет !!!

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 1693
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 26.02.11 23:48. Заголовок: PSP , я понял свою о..


PSP , я понял свою ошибку !!!

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 1694
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 27.02.11 00:06. Заголовок: Pasha пишет: Вывод:..


Pasha пишет:

 цитата:
Вывод: Андрей, откажись от этих глупостей, и используй традиционный подход.


Спасибо большое за разъяснение. Я еще в 2008 году пытался про это понять.

А как использовать традиционный подход ? Опиши технологию пожалуйста....

У меня сейчас строится условный индекс и отображается TBROWSE. Это быстро и выход за границы базы быстро пресекается, и реакция в самом TBROWSE быстрая. Без всяких кодоблоков. Эту технологию еще с Клипера 5.3 перетаскивал....




Спасибо: 0 
ПрофильЦитата Ответить
Администратор




Пост N: 1838
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 27.02.11 09:44. Заголовок: Традиционный подход ..


Традиционный подход - это использование для выборок постоянных индексов со scope по ним. Дополнительно к scope можно использовать и условие/фильтр for. Надо определить, по каким полям могут быть чаще всего выборки, и соответственно заранее создать все тэги.
Причем постоянный индекс может быть также с условием for. Но при этом индекс строится только один раз, и затем только обновляется

Спасибо: 0 
ПрофильЦитата Ответить



Пост N: 12
Зарегистрирован: 19.08.10
ссылка на сообщение  Отправлено: 27.02.11 13:13. Заголовок: Pasha: ОГРОМНОЕ спас..


Pasha: ОГРОМНОЕ спасибо за подробный и (имхо) правильный совет. Не пора ли FAQ завести на форуме?

Andrey: спасибо за "спасибо"

Andrey пишет:

 цитата:
БД из 60 000 записей, имеющей 263 поля



Широко развернулся

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 1695
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 27.02.11 15:21. Заголовок: Pasha пишет: Надо о..


Pasha пишет:

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



БД-Договоров. Список полей примерно 160. Номер договора, дата договора, адрес договора, филиал, заказчик и т.д.
Пользователь может выбрать условие поиска по всему списку полей. Сделать заранее шаблоны поиска сложно.
Так что здесь придется оставить условную индексацию с FOR.

А на другие постоянные выборки буду делать по твоим рекомендациям.
Спасибо большое Паша.

Спасибо: 0 
ПрофильЦитата Ответить
Администратор




Пост N: 1839
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 27.02.11 16:31. Заголовок: Andrey пишет: Так ч..


Andrey пишет:

 цитата:
Так что здесь придется оставить условную индексацию с FOR.



Условная индексация с for означает, что:

1) необходим цикл по всем записям таблицы для создания индекса
2) затем - цикл по записям, которые присутствуют в созданном индексе для выбора записей, удовлетворяющих условию поиска

Это менее оптимально, чем просто цикл по всей таблице без использования индекса.

Оптимальный вариант: определить реквизиты, по которым чаще всего выполняется поиск, и по ним создать индексы
Если в условии поиска есть выбранные реквизиты, то использовать соответствующий индекс, иначе - цикл по всей таблице. Все равно так будет оптимальнее, чем создание индекса с for

А самый оптимальный вариант - использовать клиент-сервер aka ads/letodb. В этом случае таблицу будет молотить сервер, а клиент только получит результат выборки без лишней загрузки сети.

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 1697
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 27.02.11 20:02. Заголовок: Pasha пишет: А сам..


Pasha пишет:

 цитата:

А самый оптимальный вариант - использовать клиент-сервер aka ads/letodb



Пробую. Перевести одну программу несложно, но у меня их несколько. Сейчас занимаюсь чисткой-подгонкой под LetoDB.
Работы уйма. Тем более раньше на Клипере из-за ограничения открытия файлов, приходилось открывать БД когда нужно было.
Сейчас смотрю все пишут по другому: открывают сразу все базы, а потом работают с ними.


Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник


Пост N: 182
Зарегистрирован: 13.10.05
ссылка на сообщение  Отправлено: 28.02.11 19:29. Заголовок: Условные индексы в н..


Условные индексы в некоторых случаях имеют право на существование. Я их применяю для построения эпизодических выборок( т.е не каждый день нужны и да же не каждую неделю). Если создать постоянные индексы со всеми вариантами построения условных, то количество индексов удвоится или утроится. А зачем? Это будет в целом тормозить работу ( обновление всех индексов). Потом в условие создания индекса можно "запихнуть" практически любые требования и они отрабатываются. При количестве записей до 200 тыс. время создания несущественно.

Короче, в каждом конкретном случае надо смотреть. И хорошо, что есть выбор

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 1709
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 24.03.11 12:18. Заголовок: Некоторые непонятки ..


Некоторые непонятки с условной индексацией.

Есть код:
nKolRecords := LASTREC()
cIndexTo := "PADL(ALLTRIM(FIELD->CNumKvar),5)"
cFilterTo := "NN==490.AND.!DELETED()"
----------------------------------------------------------------------------------
INDEX ON &cIndexTo TAG "ONE" TO ("temp.cdx") ;
EVAL SAY_PROC() ;
EVERY nKolRecords / 10 ;
WHILE &cFilterTo ADDITIVE // замена на FOR &cFilterTo ADDITIVE увеличивает построение индекса на 6 сек.
ORDSETFOCUS( "ONE" )
DBSETORDER(INDEXORD())
DBGOTOP()

где SAY_PROC() - функция рисования бегунка, возвращает всегда .T.


Если в базе записи идут в таком порядке:
запись
запись
запись
удаленная запись
запись
запись
запись


То получается НЕПОРЯДОК - в tbrowse затем отображаются ВСЕГО 3 записи.

Если WHILE заменить на FOR то в tbrowse отображаются 6 записей.

Как быть ? Что можно сделать чтоб при WHILE выводилось все 6 записи ?


Спасибо: 0 
ПрофильЦитата Ответить
Администратор




Пост N: 1853
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 24.03.11 12:37. Заголовок: Ничего При таком усл..


Ничего
При таком условии при использовании while в индекс попадут 3 записи

Спасибо: 0 
ПрофильЦитата Ответить
Администратор




Пост N: 1854
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 24.03.11 12:49. Заголовок: Андрей, почему бы не..


Андрей, почему бы не сделать постоянный условный индекс с выражением:

cIndexTo := "Str(NN)+PADL(ALLTRIM(FIELD->CNumKvar),5)"

и условием

cFilterTo := "!DELETED()"

и в для бровса делать scope по Str(490) ?


Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 1710
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 24.03.11 13:00. Заголовок: Pasha Спасибо БОЛЬШО..


Pasha Спасибо БОЛЬШОЕ за подсказку !!!
Ну не сообразил. Все еще живу ДОСовской реализацией, где каждый индексный файл - это лишнии ресурсы компа.
Уже года 3 мучаюсь, как сделать просто (без правки кода) и быстро.

Только как будет выглядеть код ?
Набросай пожалуйста примерно...



Спасибо: 0 
ПрофильЦитата Ответить
Администратор




Пост N: 1855
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 24.03.11 14:52. Заголовок: Как я понял, пример ..


Как я понял, пример нужен и для создания индекса, и для scope

Индексировать можно примерно так:

use тратата
if File(cIndexFile)
// если файл существует - просто открываем его
OrdListAdd(cIndexFile)

else
/*
иначе - создаем
заготовим массив вида:
aIndex := {;
{<tagname1>, <indexp1>, <for1>},;
{<tagname2>, <indexp2>, <for2>},;
...
со всеми индексами
*/

OrdListClear()
for each ai in aIndex

if ! Empty(ai[3])
// если задан for
OrdCondSet(ai[3], &('{||'+ai[3]+'}'))
endif
OrdCreate(cIndexFile, ai[1], ai[2], &('{||'+ai[2]+'}'))
next
OrdSetFocus(1)

endif

этот фрагмент можно улучшать по своему вкусу: добавлять еще параметры индекса
Если индексный файла существует, можно проверить, все ли нужные индексы в нем есть,
и если не все - переиндексировать

пример для бровса:

set order to <номер>
set scope to Str(490, <длина поля>)
browse()


Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 1711
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 24.03.11 15:15. Заголовок: Pasha пишет: browse..


Pasha пишет:

 цитата:
browse()



А в нем не нужно никаких хитрых кодоблоков ?

Паша спрасибо БОЛЬШОЕ за пример !!!

Спасибо: 0 
ПрофильЦитата Ответить
Администратор




Пост N: 1856
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 24.03.11 15:19. Заголовок: Andrey пишет: А в н..


Andrey пишет:

 цитата:
А в нем не нужно никаких хитрых кодоблоков ?



Для навигации - не нужно, scope установит фильтр по индексу

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 1712
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 24.03.11 16:16. Заголовок: Понятно. С этим разо..


Понятно. С этим разобрались.

Теперь другой вопрос по теме.
Если индекс "слетает", то как это можно отловить ?
А то у меня частенько на старых машинах индексы рушаться....

Если делать каждый раз условную индексацию, то знаешь наверняка что данные выберутся правильные.
А если надеяться на индекс, то при "слете" его будет вопеж юзеров - куда делись мои квартиры ...

Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 32 , стр: 1 2 All [только новые]
Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 698
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет