Автор | Сообщение |
|
| постоянный участник
|
Пост 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. Заголовок: Эх, было время, когд..
Эх, было время, когда компьютеры были компьютеры, а не суперкомпьютеры, как сейчас. И если ты не оптимизируешь код - это сразу становилось заметно. А сейчас хоть оптимизируй, хоть не оптимизируй - работает одинаково. Разве что очень крутой косяк будет заметным.
|
|
|
Ответов - 26
, стр:
1
2
All
[только новые]
|
|