:: Visual Foxpro, Foxpro for DOS
Re: медленно работает код или это нормально...
ssa

Сообщений: 13007
Откуда: Москва
Дата регистрации: 23.03.2005
ProbaSP
Я так понял, что нужно смотреть в сторону среднего значения. И забыть про
Аспид
Непонятная_логика
правильно?
Возможно. Только не используй фиксированное число для расчета среднего. Ибо, как, наверное, уже смог заметить, все получаемые числа будут стремиться к этому фиксированному числу. А оно тебе надо? Зная запись, перед/после которой надо вставить новую, таки не трудно найти вторую для определения между какими записями вставлять и какие значения использовать для расчета.

------------------
Лень - это неосознанная мудрость.
Ratings: 0 negative/0 positive
Re: медленно работает код или это нормально...
ProbaSP
Автор

Сообщений: 94
Откуда: Урал
Дата регистрации: 28.01.2016
ssa
Зная запись, перед/после которой надо вставить новую, таки не трудно найти вторую для определения между какими записями вставлять и какие значения использовать для расчета.
С фиксированным числом "нет проблем".
Можно попросить, пожалуйста, пример вашего "решения"...



Исправлено 1 раз(а). Последнее : ProbaSP, 01.03.18 13:15
Ratings: 0 negative/0 positive
Re: медленно работает код или это нормально...
ssa

Сообщений: 13007
Откуда: Москва
Дата регистрации: 23.03.2005
И добавчик: а если уж так невтерпеж пользоваться именно целыми числами (Int), то тогда уж использовать ВЕСЬ диапазн Int, от -MaxSignedInt до +MaxSignedInt, а не от нуля или единицы. Тогда и числа будут вполне читаемыми.


------------------
Лень - это неосознанная мудрость.
Ratings: 0 negative/0 positive
Re: медленно работает код или это нормально...
ProbaSP
Автор

Сообщений: 94
Откуда: Урал
Дата регистрации: 28.01.2016
ssa
а если уж так невтерпеж пользоваться именно целыми числами
не не с целыми числами я уже понял, проблем нет. Надо значит надо...

А вот
ssa
Зная запись, перед/после которой надо вставить новую
это понятно.

ssa
таки не трудно найти вторую
эмм... какую вторую?

Хочу разобраться в вашем совете!
Ratings: 0 negative/0 positive
Re: медленно работает код или это нормально...
ssa

Сообщений: 13007
Откуда: Москва
Дата регистрации: 23.03.2005
ProbaSP
ssa
Зная запись, перед/после которой надо вставить новую
это понятно.

ssa
таки не трудно найти вторую
эмм... какую вторую?
Предыдущую/последующую в зависимости от "перед/после которой надо вставить новую".

------------------
Лень - это неосознанная мудрость.
Ratings: 0 negative/0 positive
Re: медленно работает код или это нормально...
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
ssa
И опять завернутость на ЦЕЛЫЕ числа. Как среднее двух чисел может быть равно одному из них, если эти два числа не равны друг другу и НЕ (ЦЕЛЫЕ/НАТУРАЛЬНЫЕ)?
В компьютерах нет ни рациональных, ни тем более действительных (вещественных) чисел по их математическому определению - есть лишь их приближение - через тот же фоксовый тип Double, который по сути есть IEEE 754 формат binary64.
И как таковое, это "приближение" приведёт к тому, что рано или поздно "среднее" между двумя неравными числами станет совпадать с одним или вторым их них.
Т.е. от принудительной "перенумерации" отказываться не следует...
CLEAR
CREATE CURSOR test (ID I, ordinal_number B(18))
INDEX ON ordinal_number TAG ON CANDIDATE
LOCAL lnFirst
lnFirst = 0 && 0 gives maximum "division count" before underflow occured.
INSERT INTO test (ID, ordinal_number) VALUES (0, m.lnFirst)
LOCAL ln1, lnPrev, lnNext, lnInserted
FOR ln1 = 1 TO 100
LOCATE FOR ordinal_number = m.lnFirst
lnPrev = test.ordinal_number
SKIP 1
IF !EOF("test")
lnInserted = (test.ordinal_number+m.lnPrev)/2
lnNext = test.ordinal_number
ELSE
lnInserted = m.lnPrev + 1
lnNext = .NULL.
ENDIF
TRY
INSERT INTO test (ID, ordinal_number) VALUES (m.ln1, m.lnInserted)
CATCH
? "No more doubles fit between 0x" + STRCONV(BINTOC(m.lnPrev, "BR"), 15) + ;
" AND 0x" + STRCONV(BINTOC(m.lnNext, "BR"), 15) + " at step " + STR(m.ln1, 2)
ln1 = 1e10 && to exit loop
ENDTRY
ENDFOR
Обрати внимание как ВЫГЛЯДЯТ в окне browse первые 11 "порядковых номеров" - при том что кроме собственно первой записи там вовсе не нули хранятся, а 11 действительно разных чисел
Конечно, можно считать что пользователь "никогда не будет вставлять 50 элементов на одну и ту же позицию, смещая все последующие" - можно даже в документации написать что "это не баг, это фича" Но лучше всё же добавить "аварийную перенумерацию", если уж и идти таким путём.
Впрочем, для объёмов "упорядочиваемых" таким способом блоков в 200-500 записей надо хорошо постараться, чтобы перенумерация занимала таки 5 секунд. Это надо полностью наплевать на оптимизацию
Да, делать перенумерацию лучше одним запросом, примерно как Владимир написал. Только для фокса следует вручную обеспечить транзакционную целостность - update не атомарно меняет записи, так что если "в процессе" кто-то влезет и поменяет одну из записей подлежащих update - могут быть проблемы. FLOCK или замена update на replace (тот сам делает табличную блокировку для "многозаписного" варианта замены).


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: медленно работает код или это нормально...
Simple777

Сообщений: 33855
Дата регистрации: 05.11.2006
ssa
Simple777
Тут вот какое дело. Прежде чем вставлять номер между двумя записями ( взяв средне значение ), надо проверить, не получилось ли это среднее значение равным уже существующему номеру (выше или ниже).
И опять завернутость на ЦЕЛЫЕ числа. Как среднее двух чисел может быть равно одному из них, если эти два числа не равны друг другу и НЕ (ЦЕЛЫЕ/НАТУРАЛЬНЫЕ)?
Остальное совершенно неоригинально и проистекает из самой завернутости на целых числах.

"Мамаша, ваши слова очень обидные". ("Ширли-мырли").

Где речь шла у меня про целые числа? И вообще, какое это имеет значение - целые числа или дробные. Никакого отношения к предмету разговора это не имеет.

Второй момент. Если разница между значениями такова, что среднее арифметическое уже невозможно сформировать отличное от двух значений, то вот и получится, что среднеарифметическое равно одному из исходных значений.
Ладно, пример.

Положим, есть две соседние записи. У одной внутренний номер (не RECNO()!) равен 999, а у второй 1000. Внутренний номер имеет разрядность N(10). Находим среднее значение:

(1000+999)=999,5

При округлении до целого получаем 1000. Таким образом, среднее значение равно значению в одной из записей. При появлении такой ситуации перенумеровываем во всех таблицах внутренние номера с нужным шагом.

Надеюсь, теперь шериф сменит гнев на милость?
Ratings: 0 negative/0 positive
Re: медленно работает код или это нормально...
ssa

Сообщений: 13007
Откуда: Москва
Дата регистрации: 23.03.2005
Simple777
Положим, есть две соседние записи. У одной внутренний номер (не RECNO()!) равен 999, а у второй 1000. Внутренний номер имеет разрядность N(10). Находим среднее значение:
(1000+999)=999,5

При округлении до целого получаем 1000. Таким образом, среднее значение равно значению в одной из записей. При появлении такой ситуации перенумеровываем во всех таблицах внутренние номера с нужным шагом.

Надеюсь, теперь шериф сменит гнев на милость?
НЕТ. Округление и N(10) и есть демонстрация зацикленности на целых числах.
Горбатый "пример"...


------------------
Лень - это неосознанная мудрость.




Исправлено 1 раз(а). Последнее : ssa, 01.03.18 14:59
Ratings: 0 negative/0 positive
Re: медленно работает код или это нормально...
Simple777

Сообщений: 33855
Дата регистрации: 05.11.2006
Ну вот, пришел ИК и опять всё... обобщил, пока я писал ответ. Собственно, я написал то же самое, только без "теории". Кстати, менять надо номера и не везде, а только там, где есть своя индивидуальная (не сквозная на всю таблицу) нумерация. Скажем, подетальные нормы расхода материалов на сборочный узел. Внутренняя нумерация должна вестись по каждому узлу отдельно, и если в узле "коробка передач" внутренние номера уже достигли состояния невозможности вставки записей, то перенумерацию внутренних номеров надо делать только для одного этого узла, а не до всех узлов.
Ratings: 0 negative/0 positive
Re: медленно работает код или это нормально...
Simple777

Сообщений: 33855
Дата регистрации: 05.11.2006
ssa
Simple777
Положим, есть две соседние записи. У одной внутренний номер (не RECNO()!) равен 999, а у второй 1000. Внутренний номер имеет разрядность N(10). Находим среднее значение:
(1000+999)=999,5

При округлении до целого получаем 1000. Таким образом, среднее значение равно значению в одной из записей. При появлении такой ситуации перенумеровываем во всех таблицах внутренние номера с нужным шагом.

Надеюсь, теперь шериф сменит гнев на милость?
НЕТ. Округление и N(10) и есть демонстрация зацикленности на целых числах.
Горбатый "пример"...

Будем упорствовать или выискивать у меня опечатки?

Тема ясна, решение предложено. [sm128]
Ratings: 0 negative/0 positive
Re: медленно работает код или это нормально...
Аспид

Сообщений: 3475
Откуда: Москва
Дата регистрации: 01.04.2005
Поскольку все вводится лишь для сортировки, и коли не нравится мой способ (я бы попробовал его, на 99% он устроит, а понятнее некуда),
забей на int, поставь varchar(255)
И нумерацию делай 1,2,3...110
И пишешь udf которая превращает эти числа в '000...01','000...02','000...0110'
Алгоритм вставок придумаешь легко)
Сортировка будет работать.
Можно еще с DateTime поколдовать, там тоже простора много.
Но все это не так очевидно (через 5 лет), чем решение с раздвижением.
Я просто не вижу в этом решении ни одной неправильности.
(Естественно учесть особенности фокса, как ИК говорил)


------------------
Ratings: 0 negative/0 positive
Re: медленно работает код или это нормально...
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
ssa
Округление и N(10) и есть демонстрация зацикленности на целых числах.
Горбатый "пример"...
К сожалению (или счастью), современные компьютеры являются цифровыми, а не аналоговыми, и потому любые "числа" которыми они манипулируют по своей сути являются дискретными величинами - в некотором роде "целыми". Ну да, если брать два числа отдельно, то можно весьма точно хранить некоторые рациональные числа (дроби) - до достижения предела на "размер" числа (и в числителе и в знаменателе) - правда упорядочивать такие штуки уже будет несколько "неудобно". Ну и от "предела" никак не избавиться. Бесконечнозначное число в памяти компьютера представить невозможно А в математике даже множество целых чисел бесконечно, не говоря уж про рациональные и тем паче вещественные. А между тривиальными 0 и 1 как раз таки бесконечное число рациональных чисел и будет находится... Так что увы, без перенумерации - никак. Ну только "ограничивать свободу" - типа между двумя "изначально" существующими записями "вставлять" не более 20 новых
P.S. Вообще к проблеме можно подойти с другой стороны - вместо хранения "номера по порядку" хранить в записи "ссылку на следующий элемент", соответственно организуя связный список. Вставка в такую структуру потребует всего 2 операции - один insert и один update (всего одной записи - "предыдущей" - там надо поменять ссылку на "вновь добавленную" запись). Конечно же работать что через SQL что через xbase с такого рода структурой будет, мягко говоря, не очень удобно. Это тебе не банальный index on или order by


------------------
WBR, Igor




Исправлено 1 раз(а). Последнее : Igor Korolyov, 01.03.18 18:49
Ratings: 0 negative/0 positive
Re: медленно работает код или это нормально...
akvvohinc

Сообщений: 4217
Откуда: Москва
Дата регистрации: 11.11.2008
ProbaSP
в таблице bd пока 40 тыс. записей.
этим кодом изменяет примерно записей 200.
но процесс занимает примерно 4-5 секунд.
как-то долго...

При таких объемах я бы ничего не мудрил, а перенумеровывал эти 200 (в среднем) записей каждый раз.
Нужно только использовать нормальный "однопроходный" алгоритм (к чему эти циклы в цикле в виде FOR и LOCATE?), а если скорость все равно не устроит (хотя с чего бы это при 40 тыс. записей), то добавить индекс по полю Mod.

Был предложен нормальный вариант с командой UPDATE - я так и не понял, какой он показал результат (я думаю, отработает за долю секунды, глазом не успеешь моргнуть) или чем не устроил.
Ratings: 0 negative/0 positive
Re: медленно работает код или это нормально...
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Судя по предоставленному коду, нужен индекс И по полю mod, И по полю pn (два отдельных тега). Возможно ещё binary индекс по Deleted() - если в таблице кучи удалённых записей. Это даст оптимизацию запроса (update в варианте Владимира aka Аспид).


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: медленно работает код или это нормально...
akvvohinc

Сообщений: 4217
Откуда: Москва
Дата регистрации: 11.11.2008
Igor Korolyov
Это даст оптимизацию запроса (update в варианте Владимира aka Аспид).

Пока там даже оптимизировать нечего - если записей не предвидится более миллиона, то и так все будет достаточно быстро (менее секунды).
Ratings: 0 negative/0 positive
Re: медленно работает код или это нормально...
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
А ты положи табличку на слабый сервер, да за 10мб (или, не к ночи будь помянут, какой ADSL/3G) канал... Там "лишний" проход даже по сотне записей уже визуально ощутим. И разница между "обновить 500 записей" и "обновить 250 записей" - тем более за счёт достаточно логичного, дешевого и в общем то "нужного" индекса будет. А он нужен, т.к. поле "(относительный) порядковый номер" предполагает и упорядочение по нему - т.е. в Order by явно этот pn попадёт.
Про то что разница между "прочитать 40К записей, из них обновить 200" и "прочитать через индекс 200 записей и обновить их" колоссальна я как бы даже говорить не хочу.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: медленно работает код или это нормально...
akvvohinc

Сообщений: 4217
Откуда: Москва
Дата регистрации: 11.11.2008
Igor Korolyov
А ты положи табличку на слабый сервер...

Я сразу написал, что если скорость перенумерации покажется недостаточной, то проще всего добавить индекс по Mod (индекс по Pn у него и так должен быть, раз он по нему выводит или обрабатывает записи).

Но я не предлагал искусственно создавать такую ситуацию, при которой этот индекс потребуется.
Ratings: 0 negative/0 positive
Re: медленно работает код или это нормально...
ProbaSP
Автор

Сообщений: 94
Откуда: Урал
Дата регистрации: 28.01.2016
Спасибо всем!

особенно
Аспид
update bd set pn=pn+1 where mod = m.lcStr AND pn >= kolzap
INSERT INTO bd (pn,ns,mod,tdata) ;
VALUES (m.tekpn,0,m.lcStr,DATE())

доли секунды!это просто бомба...
а мне больше и не надо
ну и пусть "нелепое название" - главное мне понятно...

Ещё раз ВСЕМ спасибо!
Ratings: 0 negative/0 positive
Re: медленно работает код или это нормально...
akvvohinc

Сообщений: 4217
Откуда: Москва
Дата регистрации: 11.11.2008
ProbaSP
доли секунды!это просто бомба...
а мне больше и не надо

Но может, надо меньше?
Ratings: 0 negative/0 positive
Re: медленно работает код или это нормально...
vnkor

Сообщений: 324
Дата регистрации: 04.10.2007
Если поле pn (порядковый номер) используется только для сортировки при отображение в гриде, то не обязательно оно должно быть 1, 2, 3 и т.д. Можно его сделать 10, 20, 30 (или 100, 200, 300). Т.е. умножить все pn на 10 или 100, сразу сделав "резерв". При добавлении, как уже тут предлагалось, вычислять среднее. Если не получилось со средним - перенумеровывать.
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 24 kornienko_ru  (Гостей: 23)

© 2000-2024 Fox Club 
Яндекс.Метрика