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




Пост 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 
ПрофильЦитата Ответить
постоянный участник


Пост N: 199
Зарегистрирован: 13.10.05
ссылка на сообщение  Отправлено: 24.03.11 20:17. Заголовок: Попробуй запросы ADS..


Попробуй запросы ADS. База у тебя не такая уж и большая. Условия можно сочинять любые. Индексы , конечно помогут, но достаточно наличия по основным полям.
Во многих случаях запросы для отчетов - это то что надо.

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




Пост N: 1719
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 25.03.11 01:04. Заголовок: Vlad04 пишет: Попро..


Vlad04 пишет:

 цитата:
Попробуй запросы ADS.


Спасибо, но я не могу его использовать. Причины: он платный, и нужна еще отдельная локальная версия.
На LetoDB буду переходить. Но там пока индексы CDX (по отдельным файлам) не доделали ....

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


Пост N: 200
Зарегистрирован: 13.10.05
ссылка на сообщение  Отправлено: 25.03.11 14:57. Заголовок: Причины: он платный..



 цитата:
Причины: он платный,


Для отчетов можно использовать локальную версию - она бесплатная

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




Пост N: 1862
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 25.03.11 15:42. Заголовок: Vlad04 пишет: Для о..


Vlad04 пишет:

 цитата:
Для отчетов можно использовать локальную версию - она бесплатная



А смысл ? Для сети это будет тот же файл сервер, причем работать он будет не лучше, если не хуже, чем DBFCDX
Только ради sql-запросов ? Да и если запрос сделать неоптимально, он будет выполняться намного медленнее.
А чтобы его сделать оптимально, надо понимать, как его будет выполнять Ads, сможет ли он использовать индексы
Да и использование двух движков - ads для отчетов, dbfcdx для остального - это просто абсурд

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


Пост N: 201
Зарегистрирован: 13.10.05
ссылка на сообщение  Отправлено: 25.03.11 20:11. Заголовок: А смысл ? Если ре..



 цитата:
А смысл ?

Если результат, данные нескольких связанных баз, смысл применять ADS есть И код получается намного проще.Скорость, как правило в этих случаях не критична. Или 0.5 сек или несколько сек не так важно(нареканий не было).
Если же отчет - результат простого перебора данных таблицы , то ads не применяю.
Так ads в паре с dbfcdx применяю давно.

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




Пост N: 1863
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 25.03.11 21:57. Заголовок: Речь идет об локальн..


Речь идет об локальном или настоящем Ads ? Если о настоящем, то он безусловно лучше, чем dbfcdx, если его конечно правильно использовать
Если о локальном - то безусловно хуже, поскольку мы имеем лишний слой в виде ace - adslocal
Дальше. Разговор здесь не шел о простоте кода в ущерб быстродействию. Наоборот, мы говорили об оптимизации тяжелых операций. И простотой кода в таких случаях надо жертвовать.
А использование sql в ads local в случае сложной выборки из нескольких таблиц не спасет.
В лучшем случае ads будет делать выборку тем же способом, как она делается ручками в dbfcdx. А может и хуже.
Но правильно построенную выборку средствами dbfcdx с помощью ads local превзойти не получится.
Совместное использование и ads, и dbfcdx я считаю бессмысленным
Если есть ads server, то надо использовать только его. Если нет - то смысла в использовании ads local нет. Но если уж хочется иметь такой суррогатный sql, то надо и для всех операций использовать только ads local. Тогда dbfcdx не нужен.


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




Пост N: 1720
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 25.03.11 23:03. Заголовок: Vlad04 пишет: Если..


Vlad04 пишет:

 цитата:

Если результат, данные нескольких связанных баз, смысл применять ADS есть И код получается намного проще



У меня несколько связанных баз. Смысла переделки под ADS нет, так как проще все делается на DBFCDX и времени нет по переходу на него. Я знаю, что локальный ADS будет медленней чем DBFCDX (в форумах давно читал).
А на настоящий переходить нельзя - лицензию заказчики оплачивать не будут, ради 3-10 рабочих мест.
Так что изучаем лучше матчасть - DBFCDX ....

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




Пост N: 3917
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 24.01.15 14:58. Заголовок: Подскажите пожалуйст..


Подскажите пожалуйста как можно получить (просто для подсказки) выражение условного индекса ?
При уже построенном индексе.
Конечно можно запоминать в переменную, а потом выводить на экран, но это муторно...

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




Пост N: 4419
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 24.01.15 15:05. Заголовок: IndexKey..


IndexKey

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




Пост N: 3918
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 24.01.15 16:32. Заголовок: Dima пишет: IndexKe..


Dima пишет:

 цитата:
IndexKey


Не то ! То же самое что и :
cText := " Ключ индекса: [" + DBORDERINFO( DBOI_EXPRESSION ) + "]" + CRLF


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




Пост N: 4420
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 24.01.15 16:38. Заголовок: &(indexkey())..


&(indexkey())

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



Пост N: 12
Зарегистрирован: 05.11.14
ссылка на сообщение  Отправлено: 27.01.15 14:49. Заголовок: Pasha пишет: Андрей..


Pasha пишет:

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

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


Мне кажется Str(NN) немного не корректно ... нужно PADL()

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

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