Автор | Сообщение |
|
| постоянный участник
|
Пост N: 6370
Зарегистрирован: 12.09.06
|
|
Отправлено: 28.07.19 23:38. Заголовок: REINDEX ...
Всем привет ! Не пользовался этой командой вообще. Делал закрытие индексов и создание нового индекса. А как сделать REINDEX на драйвере CDX без закрытия индексов ? Для простоты я использую один файл - один индекс. Так привык давно делать, да и удобнее по Dbsetorder() переключаться. Делаю так: SET AUTOPEN ON USE ( cDbf ) ALIAS TEST SHARED NEW // подключается автоматом test6.cdx OrdSetFocus('ALL') Dbsetorder(1) .... // cUser := "1-user", "2-user" и т.д. cIndx := GetStartUpFolder() + "\test6." + cUser + '.cdx' DELETEFILE(cIndx) // обязательно SELECT TEST INDEX ON RECNO() TAG CODE1 TO (cIndx) FOR &cFilter ADDITIVE // условный индекс OrdSetFocus('CODE1') Dbsetorder(2) GO TOP ... Пытаюсь потом в программе сделать: SELECT(oBrw:cAlias) nOrder := INDEXORD() IF nOrder == 2 // перестроить индекс REINDEX // строка 897 ENDIF Вылетает с ошибкой: Error DBFCDX/1023 Exclusive required: W:\HB_Project\Tsb_Basic\Demo6\test6.dbf --------------------------------- Stack Trace --------------------------------- Called from ORDLISTREBUILD(0) Called from RECNOREFRESH(897) in module: demo6.prg Called from CHANGEWINBROWSE(1037) in module: demo6.prg Called from (b)MAIN(47) in module: demo6.prg
|
|
|
Ответов - 26
, стр:
1
2
All
[только новые]
|
|
|
| постоянный участник
|
Пост N: 1543
Зарегистрирован: 27.01.07
|
|
Отправлено: 29.07.19 08:17. Заголовок: REINDEX Rebuild ope..
REINDEX Rebuild open indexes in the current work area ------------------------------------------------------------------------------ Syntax REINDEX [EVAL <lCondition>] [EVERY <nRecords>] Arguments EVAL <lCondition> specifies a condition that is evaluated either for each record processed or at the interval specified by the EVERY clause. This clause is identical to the EVAL clause of the INDEX command, but must be respecified in order for the reindexing operation to be monitored since the value of <lCondition> is transient. EVERY <nRecords> specifies a numeric expression that modifies how often EVAL is evaluated. When using EVAL, the EVERY option offers a performance enhancement by evaluating the condition for every nth record instead of evaluating each record reindexed. The EVERY keyword is ignored if no EVAL condition is specified. Description REINDEX is a database command that rebuilds all open indexes in the current work area. When the reindexing operation finishes, all rebuilt indexes remain open, order is reset to one, and the record pointer is positioned to the first record in the controlling index. If any of the indexes were created with SET UNIQUE ON, REINDEX adds only unique keys to the index. If any of the indexes were created using a FOR condition, only those key values from records matching the condition are added to the index. In a network environment, REINDEX requires EXCLUSIVE USE of the current database file. Refer to the "Network Programming" chapter in the Programming and Utilities Guide for more information. Caution! REINDEX does not recreate the header of the index file when it recreates the index. Because of this, REINDEX does not help if there is corruption of the file header. To guarantee a valid index, always use INDEX ON in place of REINDEX to rebuild damaged indexes
|
|
|
|
| |
Пост N: 7080
Зарегистрирован: 17.05.05
|
|
Отправлено: 29.07.19 09:42. Заголовок: Andrey пишет: OrdSe..
Andrey пишет: цитата: | OrdSetFocus('CODE1') Dbsetorder(2) |
| А на хрена ? Коли юзаешь составной индекс , то крайне "криво" юзать Dbsetorder , так как не известно каким по счету будет нужен тэг , юзай OrdSetFocus , этого достаточно. Об этом писал еще А. Кресин.
|
|
|
|
| постоянный участник
|
Пост N: 6371
Зарегистрирован: 12.09.06
|
|
Отправлено: 29.07.19 16:18. Заголовок: Если открываю базу в..
Если открываю базу в SHARED то условный индекс всё равно могу делать в отдельном месте для каждого юзера. Мне нужно его пере индексировать. Т.е. команда REINDEX не катит. Тогда пойдём сложным путем, запоминаем открытые индексы, закрываем все индексы, восстанавливаем индексы, кроме нужного и делаем заново условную индексацию. Спасибо за разъяснения ! Dima пишет: цитата: | Dbsetorder , так как не известно каким по счету будет нужен тэг , юзай OrdSetFocus , этого достаточно. |
| Для справки в программе у меня есть отдельный показ открытых баз и всех индексов с любого окна. Мне просто надо посмотреть и всё видно - какой нужен номер Dbsetorder. Да я привык уже к этому. Переделывать много чего надо.
|
|
|
|
| Администратор
|
Пост N: 3850
Зарегистрирован: 23.05.05
|
|
Отправлено: 31.07.19 14:51. Заголовок: dbSetOrder и так реа..
dbSetOrder и так реализован через ordSetFocus. Первый из них принимает только числовой параметр индекса, а второй - и числовой, и символьный, т.е. имя тэга. Запись вида OrdSetFocus('ALL') Dbsetorder(1) эквивалентна OrdSetFocus('ALL') OrdSetFocus(1) Если All - первый тэг, то здесь два раза выполняется одна и та же операция. Номер тега в составном индексе жестко закреплен, так что к тегу можно смело обращаться как по его имени, так и по номеру. Я обычно по номеру и обращаюсь, проблем не было. Что касается индекса по условию, то, насколько я понял, индекс каждый раз перестраивается для другого условия. Не сказал бы, что это красивое решение, но сейчас не об этом. По факту это временный индекс - его построили, использовали и выбросили. Поэтому нецелесообразно держать его в общем составном индексе, лучше его формировать в отдельном индексном файле. Временный он и есть временный.
|
|
|
|
| постоянный участник
|
Пост N: 6375
Зарегистрирован: 12.09.06
|
|
Отправлено: 31.07.19 17:09. Заголовок: Pasha пишет: Что ка..
Pasha пишет: цитата: | Что касается индекса по условию, то, насколько я понял, индекс каждый раз перестраивается для другого условия. Не сказал бы, что это красивое решение, |
| А другого решения нет. Юзер как хочет, любые списки получает и делает с ними что угодно, хоть печатает, или изменяет данный список. Сколько полей в БД находиться (или спец.список полей) по стольким и выборку (условную индексацию) юзер делает и ко мне не пристаёт !!!
|
|
|
|
| постоянный участник
|
Пост N: 364
Зарегистрирован: 29.05.10
|
|
Отправлено: 01.08.19 09:39. Заголовок: Andrey пишет: А дру..
Andrey пишет: Ну что Вы, Андрей . Вы точно знаете, что есть и другие решения. Просто забыли.... Вот же Вам только что написали - Pasha пишет: цитата: | По факту это временный индекс - его построили, использовали и выбросили. Поэтому нецелесообразно держать его в общем составном индексе, лучше его формировать в отдельном индексном файле. Временный он и есть временный. |
| Если на основной базе будет хотя бы один один индекс этого достаточно. И любой пользователь будет иметь свой индексный файл на своей локальной машине построенный на основе основного. Никому не мешать и не "дергать" основную базу. Ну Вы же помните, приблизительно вот так - index on &mykey to tsmy_idx for !deleted() CUSTOM ADDITIVE Т.е. - Andrey пишет: цитата: | как хочет, любые списки получает и делает с ними что угодно |
| Кстати очень удобно и наглядно для этого использовать бровс. Мне кажется этот вопрос уже обсуждался ...
|
|
|
|
| постоянный участник
|
Пост N: 6377
Зарегистрирован: 12.09.06
|
|
Отправлено: 01.08.19 13:44. Заголовок: ММК пишет: Если на ..
ММК пишет: цитата: | Если на основной базе будет хотя бы один один индекс этого достаточно. И любой пользователь будет иметь свой индексный файл на своей локальной машине построенный на основе основного. Никому не мешать и не "дергать" основную базу. Ну Вы же помните, приблизительно вот так - index on &mykey to tsmy_idx for !deleted() CUSTOM ADDITIVE |
| Так я и делаю. На основной базе несколько индексов, и по ним строю условный индекс. cFilter := "RCity==1.AND.Kstreet=50 .AND ...... !deleted()" index on &mykey to tsmy_idx for &cFilter CUSTOM ADDITIVE
|
|
|
|
| постоянный участник
|
Пост N: 6411
Зарегистрирован: 12.09.06
|
|
Отправлено: 02.09.19 16:25. Заголовок: Вопрос возник другой..
Вопрос возник другой по базе. Нужно по условному индексу создать массив с номерами записи. На маленьких базах это происходит быстро. Если базы большие, 30 тыч.записей и больше, то тормоза... Можно ли как то ускорить этот процесс ? Сделать несколько потоков что ли или ещё как то по другому ? Вот код который у меня сейчас: aRecno := {} aBeg := WaitWinCreateModal( 'Считываю текущий список...' ) nPokaz := INT( nRecnoAll / 100 ) // показ каждые 1% FOR nI := 1 TO nRecnoAll ORDKEYGOTO(nI) AADD( aRecno, RECNO() ) IF nI % nPokaz == 0 // выводим через XXX записей cMsg := HB_NtoS(nI)+"/"+HB_NtoS(nRecnoAll) WaitWinTimer(aBeg, cMsg) // показ окна ожидания ProcessMessages() // ОБЯЗАТЕЛЬНО ! Чтобы форма НЕ замирала ENDIF NEXT WaitWinClose(aBeg) // убить окно ожидания
|
|
|
|
| Администратор
|
Пост N: 3871
Зарегистрирован: 23.05.05
|
|
Отправлено: 02.09.19 19:37. Заголовок: вместо FOR nI := 1 T..
вместо FOR nI := 1 TO nRecnoAll ORDKEYGOTO(nI) .. NEXT используй go top while ! eof() ... skip enddo или еще проще: dbeval({|| ...})
|
|
|
|
| постоянный участник
|
Пост N: 6412
Зарегистрирован: 12.09.06
|
|
Отправлено: 02.09.19 20:47. Заголовок: Pasha пишет: исполь..
Pasha пишет: А мне нужно по условному индексу создать массив с номерами записи. Я помню что dbeval({|| ...}) быстрей работает. А как его прикрутить к условному индексу ?
|
|
|
|
| Администратор
|
Пост N: 3872
Зарегистрирован: 23.05.05
|
|
Отправлено: 02.09.19 21:02. Заголовок: Andrey пишет: как ..
Andrey пишет: цитата: | как его прикрутить к условному индексу ? |
| Странный вопрос. Надо сделать этот индекс активным. Индекс ведь для этого и нужен
|
|
|
|
|
| постоянный участник
|
Пост N: 2790
Зарегистрирован: 17.02.12
|
|
Отправлено: 02.09.19 21:08. Заголовок: Andrey пишет Я помню..
Andrey пишет цитата: | Я помню что dbeval({|| ...}) быстрей работает |
| Быстрее работает цикл, блок кода отстает ~2-5 сек. на больших базах
|
|
|
|
| постоянный участник
|
Пост N: 6413
Зарегистрирован: 12.09.06
|
|
Отправлено: 02.09.19 21:47. Заголовок: Pasha пишет: Странн..
Pasha пишет: цитата: | Странный вопрос. Надо сделать этот индекс активным. Индекс ведь для этого и нужен |
| Так я и об этом пишу, и код привел по условному индексу обход базы. Забыл указать nRecnoAll := ORDKEYCOUNT() а далее FOR nI := 1 TO nRecnoAll ORDKEYGOTO(nI) AADD( aRecno, RECNO() ) ..... Даже если сразу объявить массив aRecno := Array(nRecnoAll) // создаём массив FOR nI := 1 TO nRecnoAll ORDKEYGOTO(nI) aRecno[nI] := RECNO() ...... то на малых базах - до 20 тыс. считывается RECNO() где-то 10 минут, а на больших 35-55 тыс. уже по 60 минут и более. Почему так ? Как можно ускорить ?
|
|
|
|
| постоянный участник
|
Пост N: 2792
Зарегистрирован: 17.02.12
|
|
Отправлено: 02.09.19 21:57. Заголовок: Andrey Pasha прямо ..
Andrey Pasha прямо пишет, делай go top while ! eof() ... skip enddo Зачем по индексу OdrKeyGoto(nI) ? Индекс без тебя это сделает, т.е. set order to 3 go top do while ! eof() add(aRec,recno()) skip enddo
|
|
|
|
| постоянный участник
|
Пост N: 6414
Зарегистрирован: 12.09.06
|
|
Отправлено: 02.09.19 22:09. Заголовок: SergKis пишет: Инде..
SergKis пишет: цитата: | Индекс без тебя это сделает, т.е. |
| Теперь понял ! Спасибо !
|
|
|
|
| Администратор
|
Пост N: 3874
Зарегистрирован: 23.05.05
|
|
Отправлено: 02.09.19 22:22. Заголовок: Andrey пишет: то на..
Andrey пишет: цитата: | то на малых базах - до 20 тыс. считывается RECNO() где-то 10 минут, а на больших 35-55 тыс. уже по 60 минут и более. Почему так ? Как можно ускорить ? |
| Может быть стоит переделать алгоритм ? Зачем в цикле по таблице загонять все номера записей в массив ? Есть же индекс, он и так дает индексно-последовательный доступ к нужным данным Считывать по часу данные - это жесть. Зачем в таком виде это нужно то ?
|
|
|
|
| постоянный участник
|
Пост N: 6415
Зарегистрирован: 12.09.06
|
|
Отправлено: 02.09.19 22:35. Заголовок: Pasha пишет: Считыв..
Pasha пишет: цитата: | Считывать по часу данные - это жесть. Зачем в таком виде это нужно то ? |
| Вот и я о том же. Нужно переделать алгоритм. Сделал как рекомендовал и я выпал в осадок. Вот результат: кол-во записей в БД: 52411 затрачено времени: 00:00:00.448 Блин, FOR / NEXT по базе совсем не то Вот код (кому интересно) Скрытый текст
DbSetOrder(5) nRecnoAll := ORDKEYCOUNT() aBeg := WaitWinCreateModal( 'Считываю текущий список...' ) nPokaz := INT( nRecnoAll / 100 ) // показ каждые 1% tTime := HB_DATETIME() aRecno := {} nI := 0 go top do while ! eof() AADD( aRecno, RECNO() ) skip IF nI % nPokaz == 0 // выводим через XXX записей cMsg := HB_NtoS(nI)+"/"+HB_NtoS(nRecnoAll) WaitWinTimer(aBeg, cMsg) // показ окна ожидания ProcessMessages() // ОБЯЗАТЕЛЬНО ! Чтобы форма НЕ замирала ENDIF nI++ enddo WaitWinClose(aBeg) // убить окно ожидания ? "кол-во записей в БД:", nI ? "затрачено времени:", HMG_TimeMS( HB_DATETIME() - tTime )
| Программа просто полетела в этой менюшке.
|
|
|
|
| постоянный участник
|
Пост N: 6416
Зарегистрирован: 12.09.06
|
|
Отправлено: 02.09.19 23:23. Заголовок: Сделал в другом меню..
Сделал в другом меню обработку БД, проще алгоритм, чтение и запись по текущей базе. кол-во записей в БД: 59120 Было раньше затрачено времени: 00:01:20.102 Стало теперь 00:00:10.502
|
|
|
|
| |
Пост N: 224
Зарегистрирован: 05.10.06
|
|
Отправлено: 05.09.19 13:42. Заголовок: Andrey пишет: кол-в..
Andrey пишет: цитата: | кол-во записей в БД: 59120 Было раньше затрачено времени: 00:01:20.102 Стало теперь 00:00:10.502 |
| 59 тыс база не большая, и если для выборки каждый раз индекс создаешь, то по сути делаешь двойную работу. Индекс как то может помочь если по нему многократные выборки делаешь...
|
|
|
|
| Администратор
|
Пост N: 3877
Зарегистрирован: 23.05.05
|
|
Отправлено: 05.09.19 14:01. Заголовок: Эх, было время, когд..
Эх, было время, когда компьютеры были компьютеры, а не суперкомпьютеры, как сейчас. И если ты не оптимизируешь код - это сразу становилось заметно. А сейчас хоть оптимизируй, хоть не оптимизируй - работает одинаково. Разве что очень крутой косяк будет заметным.
|
|
|
|
| постоянный участник
|
Пост N: 2803
Зарегистрирован: 17.02.12
|
|
Отправлено: 05.09.19 14:20. Заголовок: MIKHAIL пишет Индекс..
MIKHAIL пишет цитата: | Индекс как то может помочь если по нему многократные выборки делаешь... |
| У Андрея, это совместимость очень старого кода (что бы не править во всех прогах куски текстов wvt\gui). Один, динамический тэг для разных user (по именам файлов индекса каждому) и userов не так много.
|
|
|
|
|
| |
Пост N: 225
Зарегистрирован: 05.10.06
|
|
Отправлено: 05.09.19 21:06. Заголовок: Pasha пишет: хоть ..
Pasha пишет: цитата: | хоть не оптимизируй - работает одинаково. |
| Ну не скажите, можно заставить работать и суперкомпьютер как доисторическую черепаху... вопрос скорее в дензнаках вложенных либо в железо либо в мозги... смотря какие возможности и предпочтения.... на мой взгляд 1С яркий тому пример SergKis пишет: цитата: | что бы не править во всех прогах |
| ну судя по посту все же частично правит код, поэтому наверное проще вообще выкинуть построение индекса, если он одноразово используется... а если по нему выборки постоянно, без перестроения, тогда другое дело... Правильно нужно определить и использовать один общий постоянный индекс для всех, что бы ускорить выборку если оно того стоит...
|
|
|
|
| постоянный участник
|
Пост N: 2806
Зарегистрирован: 17.02.12
|
|
Отправлено: 05.09.19 22:07. Заголовок: MIKHAIL пишет Правил..
MIKHAIL пишет цитата: | Правильно нужно определить и использовать один общий постоянный индекс для всех, что бы ускорить выборку если оно того стоит... |
| В том то и дело, что клиент набирает из списка условий, нужные в конкретном запросе на данный момент и далее командой индекса этот запрос выполняется, можно конечно ставить scope, filter и делать выборку, но у Андрея так со времен clipper. Возможный вариант, да и код менять не надо под новую выборку - работает и устраивает его. Говорили с Андреем на эту тему.
|
|
|
|
| постоянный участник
|
Пост N: 6417
Зарегистрирован: 12.09.06
|
|
Отправлено: 05.09.19 22:58. Заголовок: MIKHAIL пишет: 59 т..
MIKHAIL пишет: цитата: | 59 тыс база не большая, и если для выборки каждый раз индекс создаешь, то по сути делаешь двойную работу. Индекс как то может помочь если по нему многократные выборки делаешь... |
| Кол-во записей у каждой фирмы по разному. Это средняя фирма, с кол-вом абонентов 59тыс.записей. Операция разовая, сделал и забыл. Просто привёл её в качестве примера, что код стал оптимизирован и время на операцию уменьшилось. Ранее не делал такого.
|
|
|
|
| постоянный участник
|
Пост N: 6418
Зарегистрирован: 12.09.06
|
|
Отправлено: 05.09.19 23:18. Заголовок: MIKHAIL пишет: ну с..
MIKHAIL пишет: цитата: | ну судя по посту все же частично правит код, поэтому наверное проще вообще выкинуть построение индекса, если он одноразово используется... а если по нему выборки постоянно, без перестроения, тогда другое дело... Правильно нужно определить и использовать один общий постоянный индекс для всех, что бы ускорить выборку если оно того стоит... |
| Конечно код переделываю. Переполз из терминалки на МиниГуи. Ускорение работы программы заметно по базе так очень. Единственно что с окнами задержка, медленно строятся. Карточка большая и при каждом вызове постоянно строится карточка. В терминалке карточка быстрей строится. Но наверное это тоже со временем решу, строить карточку постоянную при старте задачи. Нужно 5 карточек строить, а потом показывать под разные данные. С индексами работаю по разному. Открываю базы с постоянными индексами. Например есть постоянный индекс по адресу, при выборке строю условный индекс по нему, индекс создаётся в разы быстрей. Даже на больших базах 100 тыс. записей (кол-во заявок за несколько лет) построение условного индекса без существующих индексов операция довольно быстрая на локальном компе. Поиск по разным полям базы, включая мемо-поля. Как сделать такой поиск без условного индекса - я даже не знаю. 400 полей в базе, что юзеру придёт в голову искать, даже не думаю. Есть карточка с выбором условий - ищи что хочешь и ко мне не приставай. В сетке такие операции у меня редко кто делает. В качестве примера приводил поиск по 1 млн.записей на ЛетоДБ - там по сети всё летает. https://abonent4.ru/letodb/ SergKis пишет: цитата: | да и код менять не надо под новую выборку - работает и устраивает его. |
| Не совсем правильно. Юзеров такой поиск устраивает. На другое он не согласен. Зачем тогда переделывать, работа будет невостребована и просто выкинута в мусорку.
|
|
|
|
| |
Пост N: 226
Зарегистрирован: 05.10.06
|
|
Отправлено: 06.09.19 15:30. Заголовок: Andrey пишет: 400 п..
Andrey пишет: цитата: | 400 полей в базе, что юзеру придёт в голову искать, даже не думаю. |
| Ну если правильно понял, то набор условий FOR для индекса задает сам пользователь, на основании чего строишь индекс, а затем отобранные записи добавляешь в массив данных, после чего индекс не нужен. Если так, то нет смысла строить индекс, и потом еще раз обходить его для добавления этих записей в массив. Просто сразу делай обход всей базы данных или части на основании базового индекса с тем условием что задает пользователь. В противном случае двойная работа, а то и тройная, так как добавление записи в индекс это не одна операция... Andrey пишет: цитата: | код стал оптимизирован и время на операцию уменьшилось |
| думаю без индекса скорость возрастет в 2-3 раза
|
|
|
Ответов - 26
, стр:
1
2
All
[только новые]
|
|