Автор | Сообщение |
|
| постоянный участник
|
Пост 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 ..... В чем дело, тип ДАТА или ЧИСЛА неправильно в фильтре ??? или еще чего ??? подскажите пожалуйста.
|
|
|
Новых ответов нет
, стр:
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 нужные записи просто не попадают в индекс.
|
|
|
|
| |
Пост 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") ; //...
|
|
|
|
| Администратор
|
Пост N: 1837
Зарегистрирован: 23.05.05
|
|
Отправлено: 26.02.11 18:43. Заголовок: Да сам подход неправ..
Да сам подход неправильный. Нельзя так строить индекс. Если для индекса задать условие for, то при создании индекса будут выбраны все записи в файле, но в индекс попадут только те, которые удовлетворяют for. То есть, для построения индекса нужна выборка всех записей файла. Если задать условие while, то при построении индекса будут выбраны записи до той, которая не удовлетворяет while. Поскольку физически записи могут располагаться произвольно, то, если первая запись не удовлетворяет этому условию, то в индекс не будет включено ни одной. Если вторая - то в индексе будет одна запись. Индекс будет построен мгновенно, но он будет пустой. Сама идея использовать временный индекс с for или while для разовой выборки порочна. Если использовать for, то для построения индекса необходимо выбрать все записи файла. Но ведь при использовании существующих индексов можно задать условие выборки только части записей. Использование же while просто бесполезно, правильность индекса зависит от случая. Практически всегда он будет неправильный Вывод: Андрей, откажись от этих глупостей, и используй традиционный подход.
|
|
|
|
| постоянный участник
|
Пост N: 1692
Зарегистрирован: 12.09.06
|
|
Отправлено: 26.02.11 23:47. Заголовок: Chikanuk Спасибо бол..
Chikanuk Спасибо большое за перевод и совет !!!
|
|
|
|
| постоянный участник
|
Пост N: 1693
Зарегистрирован: 12.09.06
|
|
Отправлено: 26.02.11 23:48. Заголовок: PSP , я понял свою о..
PSP , я понял свою ошибку !!!
|
|
|
|
| постоянный участник
|
Пост N: 1694
Зарегистрирован: 12.09.06
|
|
Отправлено: 27.02.11 00:06. Заголовок: Pasha пишет: Вывод:..
Pasha пишет: цитата: | Вывод: Андрей, откажись от этих глупостей, и используй традиционный подход. |
| Спасибо большое за разъяснение. Я еще в 2008 году пытался про это понять. А как использовать традиционный подход ? Опиши технологию пожалуйста.... У меня сейчас строится условный индекс и отображается TBROWSE. Это быстро и выход за границы базы быстро пресекается, и реакция в самом TBROWSE быстрая. Без всяких кодоблоков. Эту технологию еще с Клипера 5.3 перетаскивал....
|
|
|
|
| Администратор
|
Пост N: 1838
Зарегистрирован: 23.05.05
|
|
Отправлено: 27.02.11 09:44. Заголовок: Традиционный подход ..
Традиционный подход - это использование для выборок постоянных индексов со scope по ним. Дополнительно к scope можно использовать и условие/фильтр for. Надо определить, по каким полям могут быть чаще всего выборки, и соответственно заранее создать все тэги. Причем постоянный индекс может быть также с условием for. Но при этом индекс строится только один раз, и затем только обновляется
|
|
|
|
| |
Пост N: 12
Зарегистрирован: 19.08.10
|
|
Отправлено: 27.02.11 13:13. Заголовок: Pasha: ОГРОМНОЕ спас..
Pasha: ОГРОМНОЕ спасибо за подробный и (имхо) правильный совет. Не пора ли FAQ завести на форуме? Andrey: спасибо за "спасибо" Andrey пишет: цитата: | БД из 60 000 записей, имеющей 263 поля |
| Широко развернулся
|
|
|
|
| постоянный участник
|
Пост N: 1695
Зарегистрирован: 12.09.06
|
|
Отправлено: 27.02.11 15:21. Заголовок: Pasha пишет: Надо о..
Pasha пишет: цитата: | Надо определить, по каким полям могут быть чаще всего выборки, и соответственно заранее создать все тэги. |
| БД-Договоров. Список полей примерно 160. Номер договора, дата договора, адрес договора, филиал, заказчик и т.д. Пользователь может выбрать условие поиска по всему списку полей. Сделать заранее шаблоны поиска сложно. Так что здесь придется оставить условную индексацию с FOR. А на другие постоянные выборки буду делать по твоим рекомендациям. Спасибо большое Паша.
|
|
|
|
| Администратор
|
Пост N: 1839
Зарегистрирован: 23.05.05
|
|
Отправлено: 27.02.11 16:31. Заголовок: Andrey пишет: Так ч..
Andrey пишет: цитата: | Так что здесь придется оставить условную индексацию с FOR. |
| Условная индексация с for означает, что: 1) необходим цикл по всем записям таблицы для создания индекса 2) затем - цикл по записям, которые присутствуют в созданном индексе для выбора записей, удовлетворяющих условию поиска Это менее оптимально, чем просто цикл по всей таблице без использования индекса. Оптимальный вариант: определить реквизиты, по которым чаще всего выполняется поиск, и по ним создать индексы Если в условии поиска есть выбранные реквизиты, то использовать соответствующий индекс, иначе - цикл по всей таблице. Все равно так будет оптимальнее, чем создание индекса с for А самый оптимальный вариант - использовать клиент-сервер aka ads/letodb. В этом случае таблицу будет молотить сервер, а клиент только получит результат выборки без лишней загрузки сети.
|
|
|
|
| постоянный участник
|
Пост N: 1697
Зарегистрирован: 12.09.06
|
|
Отправлено: 27.02.11 20:02. Заголовок: Pasha пишет: А сам..
Pasha пишет: цитата: | А самый оптимальный вариант - использовать клиент-сервер aka ads/letodb |
| Пробую. Перевести одну программу несложно, но у меня их несколько. Сейчас занимаюсь чисткой-подгонкой под LetoDB. Работы уйма. Тем более раньше на Клипере из-за ограничения открытия файлов, приходилось открывать БД когда нужно было. Сейчас смотрю все пишут по другому: открывают сразу все базы, а потом работают с ними.
|
|
|
|
|
| постоянный участник
|
Пост N: 182
Зарегистрирован: 13.10.05
|
|
Отправлено: 28.02.11 19:29. Заголовок: Условные индексы в н..
Условные индексы в некоторых случаях имеют право на существование. Я их применяю для построения эпизодических выборок( т.е не каждый день нужны и да же не каждую неделю). Если создать постоянные индексы со всеми вариантами построения условных, то количество индексов удвоится или утроится. А зачем? Это будет в целом тормозить работу ( обновление всех индексов). Потом в условие создания индекса можно "запихнуть" практически любые требования и они отрабатываются. При количестве записей до 200 тыс. время создания несущественно. Короче, в каждом конкретном случае надо смотреть. И хорошо, что есть выбор
|
|
|
|
| постоянный участник
|
Пост 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 записи ?
|
|
|
|
| Администратор
|
Пост N: 1853
Зарегистрирован: 23.05.05
|
|
Отправлено: 24.03.11 12:37. Заголовок: Ничего При таком усл..
Ничего При таком условии при использовании while в индекс попадут 3 записи
|
|
|
|
| Администратор
|
Пост N: 1854
Зарегистрирован: 23.05.05
|
|
Отправлено: 24.03.11 12:49. Заголовок: Андрей, почему бы не..
Андрей, почему бы не сделать постоянный условный индекс с выражением: cIndexTo := "Str(NN)+PADL(ALLTRIM(FIELD->CNumKvar),5)" и условием cFilterTo := "!DELETED()" и в для бровса делать scope по Str(490) ?
|
|
|
|
| постоянный участник
|
Пост N: 1710
Зарегистрирован: 12.09.06
|
|
Отправлено: 24.03.11 13:00. Заголовок: Pasha Спасибо БОЛЬШО..
Pasha Спасибо БОЛЬШОЕ за подсказку !!! Ну не сообразил. Все еще живу ДОСовской реализацией, где каждый индексный файл - это лишнии ресурсы компа. Уже года 3 мучаюсь, как сделать просто (без правки кода) и быстро. Только как будет выглядеть код ? Набросай пожалуйста примерно...
|
|
|
|
| Администратор
|
Пост 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()
|
|
|
|
| постоянный участник
|
Пост N: 1711
Зарегистрирован: 12.09.06
|
|
Отправлено: 24.03.11 15:15. Заголовок: Pasha пишет: browse..
Pasha пишет: А в нем не нужно никаких хитрых кодоблоков ? Паша спрасибо БОЛЬШОЕ за пример !!!
|
|
|
|
| Администратор
|
Пост N: 1856
Зарегистрирован: 23.05.05
|
|
Отправлено: 24.03.11 15:19. Заголовок: Andrey пишет: А в н..
Andrey пишет: цитата: | А в нем не нужно никаких хитрых кодоблоков ? |
| Для навигации - не нужно, scope установит фильтр по индексу
|
|
|
|
| постоянный участник
|
Пост N: 1712
Зарегистрирован: 12.09.06
|
|
Отправлено: 24.03.11 16:16. Заголовок: Понятно. С этим разо..
Понятно. С этим разобрались. Теперь другой вопрос по теме. Если индекс "слетает", то как это можно отловить ? А то у меня частенько на старых машинах индексы рушаться.... Если делать каждый раз условную индексацию, то знаешь наверняка что данные выберутся правильные. А если надеяться на индекс, то при "слете" его будет вопеж юзеров - куда делись мои квартиры ...
|
|
|
|
| постоянный участник
|
Пост N: 199
Зарегистрирован: 13.10.05
|
|
Отправлено: 24.03.11 20:17. Заголовок: Попробуй запросы ADS..
Попробуй запросы ADS. База у тебя не такая уж и большая. Условия можно сочинять любые. Индексы , конечно помогут, но достаточно наличия по основным полям. Во многих случаях запросы для отчетов - это то что надо.
|
|
|
|
|
| постоянный участник
|
Пост N: 1719
Зарегистрирован: 12.09.06
|
|
Отправлено: 25.03.11 01:04. Заголовок: Vlad04 пишет: Попро..
Vlad04 пишет: Спасибо, но я не могу его использовать. Причины: он платный, и нужна еще отдельная локальная версия. На LetoDB буду переходить. Но там пока индексы CDX (по отдельным файлам) не доделали ....
|
|
|
|
| постоянный участник
|
Пост N: 200
Зарегистрирован: 13.10.05
|
|
Отправлено: 25.03.11 14:57. Заголовок: Причины: он платный..
Для отчетов можно использовать локальную версию - она бесплатная
|
|
|
|
| Администратор
|
Пост N: 1862
Зарегистрирован: 23.05.05
|
|
Отправлено: 25.03.11 15:42. Заголовок: Vlad04 пишет: Для о..
Vlad04 пишет: цитата: | Для отчетов можно использовать локальную версию - она бесплатная |
| А смысл ? Для сети это будет тот же файл сервер, причем работать он будет не лучше, если не хуже, чем DBFCDX Только ради sql-запросов ? Да и если запрос сделать неоптимально, он будет выполняться намного медленнее. А чтобы его сделать оптимально, надо понимать, как его будет выполнять Ads, сможет ли он использовать индексы Да и использование двух движков - ads для отчетов, dbfcdx для остального - это просто абсурд
|
|
|
|
| постоянный участник
|
Пост N: 201
Зарегистрирован: 13.10.05
|
|
Отправлено: 25.03.11 20:11. Заголовок: А смысл ? Если ре..
Если результат, данные нескольких связанных баз, смысл применять ADS есть И код получается намного проще.Скорость, как правило в этих случаях не критична. Или 0.5 сек или несколько сек не так важно(нареканий не было). Если же отчет - результат простого перебора данных таблицы , то ads не применяю. Так ads в паре с dbfcdx применяю давно.
|
|
|
|
| Администратор
|
Пост 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 не нужен.
|
|
|
|
| постоянный участник
|
Пост N: 1720
Зарегистрирован: 12.09.06
|
|
Отправлено: 25.03.11 23:03. Заголовок: Vlad04 пишет: Если..
Vlad04 пишет: цитата: | Если результат, данные нескольких связанных баз, смысл применять ADS есть И код получается намного проще |
| У меня несколько связанных баз. Смысла переделки под ADS нет, так как проще все делается на DBFCDX и времени нет по переходу на него. Я знаю, что локальный ADS будет медленней чем DBFCDX (в форумах давно читал). А на настоящий переходить нельзя - лицензию заказчики оплачивать не будут, ради 3-10 рабочих мест. Так что изучаем лучше матчасть - DBFCDX ....
|
|
|
|
| постоянный участник
|
Пост N: 3917
Зарегистрирован: 12.09.06
|
|
Отправлено: 24.01.15 14:58. Заголовок: Подскажите пожалуйст..
Подскажите пожалуйста как можно получить (просто для подсказки) выражение условного индекса ? При уже построенном индексе. Конечно можно запоминать в переменную, а потом выводить на экран, но это муторно...
|
|
|
|
| |
Пост N: 4419
Зарегистрирован: 17.05.05
|
|
Отправлено: 24.01.15 15:05. Заголовок: IndexKey..
IndexKey
|
|
|
|
| постоянный участник
|
Пост N: 3918
Зарегистрирован: 12.09.06
|
|
Отправлено: 24.01.15 16:32. Заголовок: Dima пишет: IndexKe..
Dima пишет: Не то ! То же самое что и : cText := " Ключ индекса: [" + DBORDERINFO( DBOI_EXPRESSION ) + "]" + CRLF
|
|
|
|
| |
Пост N: 4420
Зарегистрирован: 17.05.05
|
|
Отправлено: 24.01.15 16:38. Заголовок: &(indexkey())..
&(indexkey())
|
|
|
|
|
| |
Пост N: 12
Зарегистрирован: 05.11.14
|
|
Отправлено: 27.01.15 14:49. Заголовок: Pasha пишет: Андрей..
Pasha пишет: цитата: | Андрей, почему бы не сделать постоянный условный индекс с выражением: cIndexTo := "Str(NN)+PADL(ALLTRIM(FIELD->CNumKvar),5)" . . . |
| Мне кажется Str(NN) немного не корректно ... нужно PADL()
|
|
|
Новых ответов нет
, стр:
1
2
All
[см. все]
|
|