Автор | Сообщение |
|
| |
Пост N: 53
Зарегистрирован: 30.05.05
|
|
Отправлено: 31.01.07 18:25. Заголовок: Правильность индекса!
Если индексный файл (Clipper 5.2E ntx) стал неактуальным (например, dbf обновили при закрытом индексе), то DbSeek() может прекрасно встать на неправильную запись и дать истину (т.е. якобы запись успешно нашлась и спозиционировалась). Нет, чтобы Клиппер проверил, соответствует ли найденная запись ключевому выражению, НО ОН ЭТОГО НЕ ДЕЛАЕТ. В результате программа встала на неправильную запись, а думает, что она - на нужной записи. Далее обновляем совершенно не ту запись и т.п. и т.п. Караул. Есть ли методика решения?
|
|
|
Ответов - 16
[только новые]
|
|
|
| постоянный участник
|
Пост N: 273
Зарегистрирован: 17.05.05
|
|
Отправлено: 31.01.07 18:34. Заголовок: Re:
Я, например, такой методики не вижу. Так как работа происходит согласно дереву ключей, хранящемуся в файле NTX, то вы и получаете ту запись, которая указана в NTX.
|
|
|
|
| |
Пост N: 624
Зарегистрирован: 17.05.05
|
|
Отправлено: 31.01.07 20:43. Заголовок: Re:
Pager Так и должно быть :) Обновляй dbf при открытом индексе. А как иначе ? :) Clipper за тебя ни чего не будет проверять по ходу. Делай это сам. Наверное кто то базу поюзал сторонней прогой или инструментом ? На самом деле нужно запрещать такие вещи делать !!! PS Поюзали видимо с помощью access , foxpro или еще чем то..........низя это делать если важны данные в программе и результат ее работы. Руки бы пообрывал таким умельцам !!!
|
|
|
|
| |
Пост N: 34
Зарегистрирован: 15.11.05
|
|
Отправлено: 31.01.07 20:45. Заголовок: Re:
Pager пишет: цитата: | Есть ли методика решения? |
| пробовал такую методику, где-то тащил в Инете 1. В зависимости от к-ва записей в ДБФ берем случайным образов номера записей // --- Номера записей для проверки --- AADD( aNNN, 1 ) IF ( Reccount() > 1 ) AADD( aNNN, Reccount() ) IF ( Reccount() > 2 ) AADD( aNNN, Int( RANDOM()%( Reccount()-1 ) ) + 1 ) IF ( Reccount() > 5 ) AADD( aNNN, Int( RANDOM()%( Reccount()-1 ) ) + 1 ) AADD( aNNN, Int( RANDOM()%( Reccount()-1 ) ) + 1 ) ENDIF ENDIF //> 2 ENDIF // > 1 ASORT( aNNN ) // по порядку номера aB:=&("{||"+ORDKEY()+"}" ) FOR j=1 TO Len( aNNN ) DbGoTo( aNNN[ j ] ) Value := Eval( aB )//Значение индексного выражения для этой записи Seek Value // поиск значения по индесу x:= Eval( aB ) // вычисляем уже для этой записи IF Value != x ) )// Ошибка WAIT ERROR ; "Файл "+Alias() + " Индекс N "+Str( i, 2 )+";"+ ; "индексное выражение :"+ OrdKey( i )+";"+ ; "Надо "+Substr( XTOC( Value ), 1, 60 )+";"+ ; "Есть "+Substr( XTOC( x ), 1, 60 )+";"+ ; "запись "+Str( aNNN[ j ], 7 )+";"+ ; "не соотвествует содержимому файла БД." ===== P.S. У самого давно уже выключено, т.к. смысла нет...
|
|
|
|
| |
Пост N: 625
Зарегистрирован: 17.05.05
|
|
Отправлено: 31.01.07 20:51. Заголовок: Re:
lista пишет: цитата: | пробовал такую методику, где-то тащил в Инете |
| у меня эта метода (ну почти она) включена по сей день на всякий пожарный , но мои пользователи сторонние проги не юзают на рабочих базах и предупреждены что могут быть глюки. По ходу эта метода не спасет Pager , так как записи проверяются случайным образом а чекать все это будет большущий тормозок ! ;)
|
|
|
|
| |
Пост N: 6
Зарегистрирован: 18.01.07
|
|
Отправлено: 31.01.07 23:10. Заголовок: Re:
У нас принята такая методика : при выходе из проги всем индексам ставится дата и время, как и дбф-ам - а при входе, соответственно, проверяется... хоть один не совпал - переиндексация базы...
|
|
|
|
| |
Пост N: 5
Зарегистрирован: 03.01.07
|
|
Отправлено: 01.02.07 07:10. Заголовок: Re:
Pager пишет: цитата: | Нет, чтобы Клиппер проверил, соответствует ли найденная запись ключевому выражению, НО ОН ЭТОГО НЕ ДЕЛАЕТ. |
| ах-ах-ах... ну сам проверяй, кто мешает func xKeyData(Order) local i,RddName RddName:=rddname() do case case RddName of: "SIXCDX","SIXNSX" ret sx_KeyData(Order) case RddName of: "DBFNTXAX","DBFCDXAX" ret ax_KeyVal(Order) other if !empty(OrdKey()) ret &(OrdKey()) end end ret NIL Сикать так: func SeekWithCheck(Key) if dbSeek(Key) .and. xKeyData(Key) = Key // set exact == OFF ret .T. endif dbGoto(lastrec()+1) ; dbSkip() ret .F.
|
|
|
|
| |
Пост N: 6
Зарегистрирован: 03.01.07
|
|
Отправлено: 01.02.07 07:25. Заголовок: Re:
Peretsc пишет: цитата: | У нас принята такая методика : при выходе из проги всем индексам ставится дата и время, как и дбф-ам - а при входе, соответственно, проверяется... хоть один не совпал - переиндексация базы... |
| 1) В некоторых ОС пока файл открыт другой станцией - дату и время обновить нельзя. 2) Возникает проблема совместимости с другим софтом. Например, редактор дбф. Так же видел монстрообразные системы, которые состоят из множества отдельных EXE-модулей (половина из которых - ночные автономные процессы, которые тусуют данные). Их исходники не всегда доступны. А какие именно данные обрабатывает (даже внутри одного модуля) - зависит от расклада. То есть навесить в пакетный файл после этого модуля прописку даты-времени - проблематично. Даже если быть на 100% уверенным, что данный процесс обработает такие-то файлы - прописка даты-времени может не выполниться, т.к. параллельно работает еще один процесс (см пункт 1) 3) Работают 10 станций. Одна из них зависла, не успев прописать в индекс правильные данные. Индекс уже неверен. Остальные 8 закончили работу. Самая последняя вышла и установила дату-время индексного файла. Имеем неверный индекс с прописанной датой-временем. Все-таки seek надо проверять. Хотя (как сейчас скажут) и это не панацея без транзакций )
|
|
|
|
| |
Пост N: 35
Зарегистрирован: 15.11.05
|
|
Отправлено: 01.02.07 09:46. Заголовок: Re:
А может нужно не бороться, не с последствиями (индекс разрушен), а с причинами разрушения!
|
|
|
|
| |
Пост N: 7
Зарегистрирован: 03.01.07
|
|
Отправлено: 01.02.07 13:49. Заголовок: Re:
Конечно. А SeekWithCheck - как раз и будет служить индикатором, насколько такая борьба успешна
|
|
|
|
| |
Не зарегистрирован
Зарегистрирован: 01.01.70
|
|
Отправлено: 01.02.07 18:52. Заголовок: По поводу seekwithcheck
Я понимаю, как можно написать свой seek(), чтобы самому делать контроль индекса. Более того, можно даже подменить стандартный dbseek собственным, через #translate. Но это будет не так эффективно, как если бы клиппер делал это изнутри. Я думал, что может быть есть какие-то настройки и т.п. Кстати, под ADS вроде стандартный dbseek просто не находит запись и выдает .F., а вот без ADS прекрасно "находит" не ту запись и встает на нее. Значит, под ADS он всё-таки, видимо, проверяет соответствие найденной записи индексному выражению. Но к сожалению нам надо работать не только под ADS. Вот я и подумал, нет ли какой-то настроечки.
|
|
|
|
| |
Пост N: 41
Зарегистрирован: 11.12.06
|
|
Отправлено: 01.02.07 19:01. Заголовок: Re:
serega пишет: цитата: | Но это будет не так эффективно, как если бы клиппер делал это изнутри. |
| Замерь разницу в секундых между тысячей вызовов dbSeek и тысячей вызовов SeekWithCheck
|
|
|
|
|
| |
Не зарегистрирован
Зарегистрирован: 01.01.70
|
|
Отправлено: 01.02.07 19:37. Заголовок: По поводу борьбы с причинами порчи индексов
Бороться с причинами порчи индексов можно и нужно (например, не открывать без индексов и т.п.). Но всё это может лишь уменьшить вероятность порчи индекса. Индекс может испортиться по 1000 причинам, среди которых самая банальная - это любой сбой (хоть отключение питания) в момент корректировки (и даже вне момента корректировки, если данные задержались в сети, что тоже может быть по 1000 причинам).
|
|
|
|
| |
Не зарегистрирован
Зарегистрирован: 01.01.70
|
|
Отправлено: 01.02.07 19:55. Заголовок: замер разницы между dbseek и своим seek
Не замерял, но тут важно, в сети это или на локале. Кроме того, неприятно, что приходится использовать макро (&). Думаю, это всё-таки должно увеличить время, особенно для сложных индексных выражений. Но, с другой стороны, это видимо единственный трезвый выход и его надо взять на вооружение. Если только у клиппера всё же нет какой-то настроечки (т.к. изнутри клиппера это было бы сделать совершенно естественно и разумно). По поводу выборочной проверки индексов (это предлагалось выше): есть это у меня, но мало спасает. На файлах с 500 000 записей выборка в 500 записей - это очень непредставительно, а больше - жаль траты времени.
|
|
|
|
| |
Пост N: 68
Зарегистрирован: 07.08.06
|
|
Отправлено: 02.02.07 11:23. Заголовок: Re:
Чтобы индексы перестали "слетать", надо устранить первопричину этого: обработку этих индексов на клиентских машинах. А для этого надо приложение переписать под АДС. Когда я сделал это, то забыл об этой проблеме. Индексы пришлось перестраивать только один раз за прошедший год, и то - сам был виноват (перетряхивал в аврале .dbf-ники без индексов и забыл их после перестроить).
|
|
|
|
| |
Пост N: 8
Зарегистрирован: 03.01.07
|
|
Отправлено: 02.02.07 12:43. Заголовок: Re:
serega пишет: цитата: | неприятно, что приходится использовать макро (&). жаль траты времени. |
| еще раз. замерь время! получи разницу во времени. она будет измеряться долями секунды страшные сказки о тормозах & были актуальны на IBM-PC 8086 с частотой 4мегагерца сейчас гигагерцы слава богу. дополнительное вычисление &ordkey() при seek даст замедление, которое можно замерить лишь секундомером в цикле из 1000 повторений. На глаз - неощутимо
|
|
|
|
| |
Пост N: 25
Зарегистрирован: 15.12.06
|
|
Отправлено: 06.02.07 14:34. Заголовок: Re: - новое!
Pager пишет: цитата: | Нет, чтобы Клиппер проверил, соответствует ли найденная запись ключевому выражению, НО ОН ЭТОГО НЕ ДЕЛАЕТ. |
| Вообще-то это логично, что не проверяется без специальных указаний, т.к. на это тратится время. Конечно, для одиночных поисков без разницы, но если большую базу лопатить как следует - разница заметна. Я когда-то проверял на Клиппере 5.01 - при dbSeek() .dbf вообще не читается (требовался хитрый поиск в цикле, где полезной информацией после dbSeek был номер записи, и читать .dbf требовалось только в самом конце). А ведь .ntx обычно на порядок меньше .dbf, так что на скорость влияет (при миллионах записей). А насчёт переиндексации - я делал в своё время так: для каждого .dbf указывал, какие .ntx c ним связаны, и при несоответствии даты-времени (а также при отсутствии .ntx) переиндексируется всё, правда, надо учитывать, что .ntx может не меняться при изменении неключевого поля.
|
|
|
|