On-line: PSP, гостей 2. Всего: 3 [подробнее..]
АвторСообщение



Пост N: 53
Зарегистрирован: 30.05.05
ссылка на сообщение  Отправлено: 31.01.07 18:25. Заголовок: Правильность индекса!


Если индексный файл (Clipper 5.2E ntx) стал неактуальным (например, dbf обновили при закрытом индексе), то DbSeek() может прекрасно встать на неправильную запись и дать истину (т.е. якобы запись успешно нашлась и спозиционировалась). Нет, чтобы Клиппер проверил, соответствует ли найденная запись ключевому выражению, НО ОН ЭТОГО НЕ ДЕЛАЕТ. В результате программа встала на неправильную запись, а думает, что она - на нужной записи. Далее обновляем совершенно не ту запись и т.п. и т.п. Караул.
Есть ли методика решения?

Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 16 [только новые]


постоянный участник


Пост N: 273
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 31.01.07 18:34. Заголовок: Re:


Я, например, такой методики не вижу. Так как работа происходит согласно дереву ключей, хранящемуся в файле NTX, то вы и получаете ту запись, которая указана в NTX.

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




Пост N: 624
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 31.01.07 20:43. Заголовок: Re:


Pager
Так и должно быть :)
Обновляй dbf при открытом индексе. А как иначе ? :)
Clipper за тебя ни чего не будет проверять по ходу. Делай это сам.
Наверное кто то базу поюзал сторонней прогой или инструментом ?
На самом деле нужно запрещать такие вещи делать !!!

PS
Поюзали видимо с помощью access , foxpro или еще чем то..........низя это делать если важны данные
в программе и результат ее работы. Руки бы пообрывал таким умельцам !!!

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



Пост 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.
У самого давно уже выключено, т.к. смысла нет...

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




Пост N: 625
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 31.01.07 20:51. Заголовок: Re:


lista пишет:

 цитата:
пробовал такую методику, где-то тащил в Инете


у меня эта метода (ну почти она) включена по сей день на всякий пожарный , но мои
пользователи сторонние проги не юзают на рабочих базах и предупреждены что могут
быть глюки.
По ходу эта метода не спасетPager , так как записи проверяются случайным образом а чекать все
это будет большущий тормозок ! ;)

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



Пост N: 6
Зарегистрирован: 18.01.07
ссылка на сообщение  Отправлено: 31.01.07 23:10. Заголовок: Re:


У нас принята такая методика : при выходе из проги всем индексам ставится дата и время, как и дбф-ам - а при входе, соответственно, проверяется... хоть один не совпал - переиндексация базы...

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



Пост 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.

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



Пост N: 6
Зарегистрирован: 03.01.07
ссылка на сообщение  Отправлено: 01.02.07 07:25. Заголовок: Re:


Peretsc пишет:

 цитата:
У нас принята такая методика : при выходе из проги всем индексам ставится дата и время, как и дбф-ам - а при входе, соответственно, проверяется... хоть один не совпал - переиндексация базы...



1) В некоторых ОС пока файл открыт другой станцией - дату и время обновить нельзя.
2) Возникает проблема совместимости с другим софтом. Например, редактор дбф. Так же видел монстрообразные системы, которые состоят из множества отдельных EXE-модулей (половина из которых - ночные автономные процессы, которые тусуют данные). Их исходники не всегда доступны. А какие именно данные обрабатывает (даже внутри одного модуля) - зависит от расклада. То есть навесить в пакетный файл после этого модуля прописку даты-времени - проблематично. Даже если быть на 100% уверенным, что данный процесс обработает такие-то файлы - прописка даты-времени может не выполниться, т.к. параллельно работает еще один процесс (см пункт 1)
3) Работают 10 станций. Одна из них зависла, не успев прописать в индекс правильные данные. Индекс уже неверен. Остальные 8 закончили работу. Самая последняя вышла и установила дату-время индексного файла. Имеем неверный индекс с прописанной датой-временем.

Все-таки seek надо проверять. Хотя (как сейчас скажут) и это не панацея без транзакций )

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



Пост N: 35
Зарегистрирован: 15.11.05
ссылка на сообщение  Отправлено: 01.02.07 09:46. Заголовок: Re:


А может нужно не бороться, не с последствиями (индекс разрушен), а с причинами разрушения!

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



Пост N: 7
Зарегистрирован: 03.01.07
ссылка на сообщение  Отправлено: 01.02.07 13:49. Заголовок: Re:


Конечно. А SeekWithCheck - как раз и будет служить индикатором, насколько такая борьба успешна

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



Не зарегистрирован
Зарегистрирован: 01.01.70
ссылка на сообщение  Отправлено: 01.02.07 18:52. Заголовок: По поводу seekwithcheck


Я понимаю, как можно написать свой seek(), чтобы самому делать контроль индекса. Более того, можно даже подменить стандартный dbseek собственным, через #translate.
Но это будет не так эффективно, как если бы клиппер делал это изнутри. Я думал, что может быть есть какие-то настройки и т.п. Кстати, под ADS вроде стандартный dbseek просто не находит запись и выдает .F., а вот без ADS прекрасно "находит" не ту запись и встает на нее. Значит, под ADS он всё-таки, видимо, проверяет соответствие найденной записи индексному выражению. Но к сожалению нам надо работать не только под ADS. Вот я и подумал, нет ли какой-то настроечки.

Спасибо: 0 
Цитата Ответить



Пост N: 41
Зарегистрирован: 11.12.06
ссылка на сообщение  Отправлено: 01.02.07 19:01. Заголовок: Re:


serega пишет:

 цитата:
Но это будет не так эффективно, как если бы клиппер делал это изнутри.



Замерь разницу в секундых между тысячей вызовов dbSeek и тысячей вызовов SeekWithCheck

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



Не зарегистрирован
Зарегистрирован: 01.01.70
ссылка на сообщение  Отправлено: 01.02.07 19:37. Заголовок: По поводу борьбы с причинами порчи индексов


Бороться с причинами порчи индексов можно и нужно (например, не открывать без индексов и т.п.). Но всё это может лишь уменьшить вероятность порчи индекса. Индекс может испортиться по 1000 причинам, среди которых самая банальная - это любой сбой (хоть отключение питания) в момент корректировки (и даже вне момента корректировки, если данные задержались в сети, что тоже может быть по 1000 причинам).

Спасибо: 0 
Цитата Ответить



Не зарегистрирован
Зарегистрирован: 01.01.70
ссылка на сообщение  Отправлено: 01.02.07 19:55. Заголовок: замер разницы между dbseek и своим seek


Не замерял, но тут важно, в сети это или на локале. Кроме того, неприятно, что приходится использовать макро (&). Думаю, это всё-таки должно увеличить время, особенно для сложных индексных выражений. Но, с другой стороны, это видимо единственный трезвый выход и его надо взять на вооружение. Если только у клиппера всё же нет какой-то настроечки (т.к. изнутри клиппера это было бы сделать совершенно естественно и разумно).
По поводу выборочной проверки индексов (это предлагалось выше): есть это у меня, но мало спасает. На файлах с 500 000 записей выборка в 500 записей - это очень непредставительно, а больше - жаль траты времени.

Спасибо: 0 
Цитата Ответить



Пост N: 68
Зарегистрирован: 07.08.06
ссылка на сообщение  Отправлено: 02.02.07 11:23. Заголовок: Re:


Чтобы индексы перестали "слетать", надо устранить первопричину этого: обработку этих индексов на клиентских машинах. А для этого надо приложение переписать под АДС. Когда я сделал это, то забыл об этой проблеме. Индексы пришлось перестраивать только один раз за прошедший год, и то - сам был виноват (перетряхивал в аврале .dbf-ники без индексов и забыл их после перестроить).

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



Пост N: 8
Зарегистрирован: 03.01.07
ссылка на сообщение  Отправлено: 02.02.07 12:43. Заголовок: Re:


serega пишет:

 цитата:
неприятно, что приходится использовать макро (&).
жаль траты времени.



еще раз. замерь время! получи разницу во времени. она будет измеряться долями секунды

страшные сказки о тормозах & были актуальны на IBM-PC 8086 с частотой 4мегагерца

сейчас гигагерцы слава богу. дополнительное вычисление &ordkey() при seek даст замедление, которое можно замерить лишь секундомером в цикле из 1000 повторений. На глаз - неощутимо

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



Пост 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 может не меняться при изменении неключевого поля.


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

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