On-line: гостей 0. Всего: 0 [подробнее..]
АвторСообщение
постоянный участник




Пост N: 1585
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 07.12.10 13:32. Заголовок: Как правильно сделаь выборку по индексу ?


Всем привет. Наконец то дошли руки до оптимизации, но как сделать не знаю.

Имеется большая база (500тыс. записей и более) поступивших платежей от жителей.
Раз в месяц эти поступившие платежи перекидываются в другую базу.
Запись которая уже успешно обработана (т.е. перекинута в другую базу) помечается ( ну допустим в поле NCALC записывается 1 ) !

Чтоб не просматривать всегда всю базу, я раньше пробовал делать условную индексацию всей БД
с условиями "NCALC < 1 .AND. DELETED()==.F."

Но при обработке записи, когда записываешь в поле NCALC = 1, происходит вылет с ошибкой.
Уже не помню какой.

Приходиться сейчас ВСЕГДА перелопачивать ВСЮ базу, типа:

do while !EOF()
IF NCALC <1
// моя обработка
ENDIF
skip
enddo

Это медленно, даже если просто пропускаешь запись....


Подскажите как этого избежать !
Или другие алгоритмы...

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


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


Пост N: 55
Зарегистрирован: 29.05.06
ссылка на сообщение  Отправлено: 07.12.10 16:47. Заголовок: Думаю, это происходи..


Думаю, это происходит потому, что текущая обрабатываемая запись при записи NCALC := 1 выходит из индекса, по которому идёт переборка. И следующий skip делается от записи, которая фактически индексу не принадлежит...

Попробуйте так

dbgotop()
do while ! eof() // Пока есть хоть одна соответствующая условному индексу ( необработанная ) запись
// обработка , в результате чего первая запись в индексе ВЫЧЁРКИВАЕТСЯ из списка...
dbgotop() // Идём на запись, которая стала первой в индексе в результате вычёркивания предыдущей
enddo

Или так

do while .T.
dbgotop()
if eof()
exit
endif
// Обработка
enddo





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





Пост N: 171
Зарегистрирован: 12.11.06
ссылка на сообщение  Отправлено: 07.12.10 20:27. Заголовок: Может опять, чего-то..


Может опять, чего-то не допонял...
Делаем индексный файл(индекс): name_ind into ncalc
Активируем его, например DbSetOrder(x)

DbGoTop()
do whil ncalc < 1
операторы
endd

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник


Пост N: 1006
Зарегистрирован: 09.10.06
ссылка на сообщение  Отправлено: 07.12.10 20:50. Заголовок: Andrey пишет: когда..


Andrey пишет:

 цитата:
когда записываешь в поле NCALC = 1, происходит вылет с ошибкой.


И что вы пытаетесь записать в числовое поле ? Подсказка:

 цитата:
PROCEDURE main() 
LOCAL NCALC

? ValType( NCALC = 1 )
? ValType( NCALC := 1 )

RETURN



И еще ! DELETED() смотрится лучше, чем DELETED() == .F.

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 1586
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 07.12.10 21:04. Заголовок: Петр пишет: И что в..


Петр пишет:

 цитата:
И что вы пытаетесь записать в числовое поле ? Подсказка:


Ошибся в написании, конечно же FIELD->NCALC := 1 !

Петр пишет:

 цитата:
И еще ! DELETED() смотрится лучше, чем DELETED() == .F.


Учту.


Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 1587
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 07.12.10 21:10. Заголовок: AndreyZh пишет: DbG..


AndreyZh пишет:

 цитата:
DbGoTop()
do whil ncalc < 1
операторы
enddо



Да вылетит это. Не правильно написано просто !

DbGoTop()
do while FIELD->NCALC < 1
// проверка записи в другую базу
// если все нормально, то пишем в поле FIELD->NCALC := 1 !
FIELD->NCALC := 1
skip
enddo


Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник


Пост N: 1007
Зарегистрирован: 09.10.06
ссылка на сообщение  Отправлено: 07.12.10 21:26. Заголовок: Ваш код и код ошибки..


Ваш код и код ошибки в студию. А то разговор ни о чем получается.
Если у вас есть индех, то правильное использование DbEval всегда быстрее выполняется чем
do while
enddo


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





Пост N: 172
Зарегистрирован: 12.11.06
ссылка на сообщение  Отправлено: 07.12.10 22:10. Заголовок: Сейчас проверил код ..


Сейчас проверил код на Clipper, замещая ключевое поле. У Вас должно сработать

DbGoTop()
do while FIELD->NCALC < 1
// проверка записи в другую базу

// если все нормально, то пишем в поле FIELD->NCALC := 1 !
FIELD->NCALC := 1
skip
enddo

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 1588
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 07.12.10 22:26. Заголовок: G-Serge пишет: Дума..


G-Serge пишет:

 цитата:
Думаю, это происходит потому, что текущая обрабатываемая запись при записи NCALC := 1 выходит из индекса, по которому идёт переборка. И следующий skip делается от записи, которая фактически индексу не принадлежит...


Я так же думал, но не знал как побороть !

Сделал тестовый пример, он не вылетает.
Вспомнил, что на Клипере 5.3 делал такое, так вот он вылетал.

Сделал на хХарборе, не вылетает, но и правильно все записи не обрабатывает.

Смотрите тестовый пример:
http://files.mail.ru/8SNB81<\/u><\/a>

Кто может подсказать правильное решение ?
Заместо 1 записываю 50. Но это не важно.


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





Пост N: 173
Зарегистрирован: 12.11.06
ссылка на сообщение  Отправлено: 07.12.10 22:45. Заголовок: Вы делаете условную ..


Вы делаете условную индексацию "plata", да потом в ней еще меняете значение ключевого поля, сканируя все виды индексов этого файла... Увы это выше уровня моего понимания Когда приводил и тестил пример у меня был ключевой индекс (который заменял) и делал "прямой" скан таблицы

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 1589
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 07.12.10 22:59. Заголовок: AndreyZh пишет: Увы..


AndreyZh пишет:

 цитата:
Увы это выше уровня моего понимания



Так я и писал, что такое делал раньше.
А если переделать на ваш вариант ? Что получиться и как будет работать ?

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник


Пост N: 56
Зарегистрирован: 29.05.06
ссылка на сообщение  Отправлено: 07.12.10 23:01. Заголовок: Что, вот такой вариа..


Что, вот такой вариант неправильно работает ?

do while .T.
dbgotop() // Идём на первую запись с NCALC == 0
if eof() // Если нет записей с NCALC == 0
exit
endif
NCALC := 1 // Вычёркиваем
enddo

Тогда во так...

do while .T.
If ! PLATA->(dbseek(0)) // Ищем запись с NCALC==0
// Если не нашли - выходим
exit
endif
NCALC := 1 // Вычёркиваем
enddo

И не надо без лишней необходимости к индексам по условию прибегать, я думаю...

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




Пост N: 1707
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 07.12.10 23:28. Заголовок: Насколько я понял, з..


Насколько я понял, задача сводится к циклу по значению индексного поля xOld с присвоением ему значения xNew. Условный индекс или нет - несущественно.

Предлагаю 2 варинта решения:

Вариант 1

while dbSeek(xOld)
... (обработка)
Field->FName := xNew
enddo

Вариант 2

aRecs := {}
dbSeek(xOld)
while FName = xOld
... (обработка)
AADD(aRecs, RecNo())
skip
enddo

AEval(aRecs, {|n| dbGoto(n), Field->FName := xNew})

Блокировки, сворачивание цикла через dbEval, соль и пряности добавить по вкусу.

По скорости второй вариант даже предпочтительнее, поскольку множественный seek будет выполняться медленнее, чем простой цикл, и затем цикл с goto


Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 1590
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 08.12.10 15:51. Заголовок: Pasha пишет: По ско..


Pasha пишет:

 цитата:
По скорости второй вариант даже предпочтительнее, поскольку множественный seek будет выполняться медленнее, чем простой цикл, и затем цикл с goto


Вот это интересно ! Я даже и не подымал о такой простой вещи - создать массив нужных записей обработки !
А время на создание массива много будет тратиться ? С учетом если примерно 50-90 тыс.записей нужно обрабатывать ежемесячно ?


А что будет быстрей работать ?
AEval(aRecs, {|n| dbGoto(n), Field->FName := xNew})
или
FOR nI:=1 TO LEN(aRecs)
dbGoto(aRecs[nI])
// Бегунок
// Обработка (запись в другую БД)
NEXT




Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник


Пост N: 57
Зарегистрирован: 29.05.06
ссылка на сообщение  Отправлено: 08.12.10 19:26. Заголовок: А какой размер масси..


А какой размер массива максимальный, кстати ?

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




Пост N: 1708
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 08.12.10 19:30. Заголовок: Быстрее всего будет ..


Быстрее всего будет работать

FOR each nI in aRecs)
dbGoto(nI)
// Бегунок
// Обработка (запись в другую БД)
NEXT

Поскольку при выполнении блока кода в aeval vm harbour запускается еще раз для каждого элемента массива

Что касается заполнения массива - думаю, время будет приемлемым

достаточно сделать тест:

nSec := Seconds()
for nI := 1 to 100000
AADD(aRecs, nI)
next
? Seconds() - nSec

Слабое место в таком алгоритме то, что если программа в первом цикле обработки вдруг споткнется на ровном месте аварийно завершится, то второй цикл выполнен не будет

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





Пост N: 174
Зарегистрирован: 12.11.06
ссылка на сообщение  Отправлено: 08.12.10 20:39. Заголовок: G-Serge пишет: А ка..


G-Serge пишет:

 цитата:
А какой размер массива максимальный, кстати ?


Определяется размером доступной памяти - сдуру решил перепроверить на 20Gb прервал.

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



Пост N: 90
Зарегистрирован: 04.12.07
ссылка на сообщение  Отправлено: 09.12.10 13:21. Заголовок: // По условному инде..


// По условному индексу

do while .T.
dbgotop()
do while ! eof()
if FIELD->NCALC = 0
FIELD->NCALC := 1
// Запись выпадает из условного индекса
// Последовательность обработки по индексу сбивается
// Необходимо начинать всё сначала
exit
endif
enddo
if eof()
exit
endif
enddo

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

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