Автор | Сообщение |
|
| |
Пост N: 2792
Зарегистрирован: 17.05.05
|
|
Отправлено: 18.03.13 17:35. Заголовок: Ascan ?
Есть массив вида {{},{},{}} поиск веду в первом элементе do while !eof() .. if ascan(klnmas[1],{|fff| fff==nakl_r1->kod_kl})==0 skip loop endif ....... skip enddo медленновато что то или меня уже плющит.... есть какой то другой аналог Ascan который пошустрее работает ? Понятно что вот так быстрее будет if ascan(klnmas[1],nakl_r1->kod_k)==0 skip loop endif RDD скипает быстрее чем работает Ascan с блоком кода....
|
|
|
Ответов - 44
, стр:
1
2
3
All
[только новые]
|
|
|
| постоянный участник
|
Пост N: 170
Зарегистрирован: 17.02.12
|
|
Отправлено: 20.03.13 14:23. Заголовок: Pasha пишет:Конечно,..
Pasha пишет: цитата: | Конечно, при использовании хеша добавление в него происходит медленнее, чем при добавлении элемента в массив. Это тоже самое, что добавлять записи в файл с индексом медленнее, чем в файл без индекса, так как в первом случае еще обновляется индекс. Выигрыш достигается затем при поиске по ключу. |
| В bcc использовал вашу функцию AADDU(<aArray>, <xKey>, <nSum1>, [nSum2], ...) при переходе на msvc она не перенеслась, стал использовать Hash (class bkHash, sum method. см. выше), протестировал по скорости в bcc оба способа. Ваш на десятые доли секунды быстрее (тестировал одной на годовой базе). Поэтому очень спокойно перешел на Hash.
|
|
|
|
| |
Пост N: 2817
Зарегистрирован: 17.05.05
|
|
Отправлено: 20.03.13 16:17. Заголовок: Dima пишет: hb_hEva..
Dima пишет: цитата: | hb_hEval( hmas, {|key,sval,ind| if(sval[1]==3,aadd(fmas,key),)}) // при размере массива 700000 записей hb_hEval работает 530 мс , хочется что то побыстрее |
| dbeval( {|| hmas[recno()]:={kod_kl,nomer}}) ? len(hmas) // 700000 ключей fmas:={} nsec:=seconds() hb_hEval( hmas, {|key,sval,ind| if(sval[1]==5,aadd(fmas,key),)}) ? (seconds()-nsec)*1000 // 594 mc fmas:={} nsec:=seconds() for each v in hmas if v:__enumValue()[1]==5 aadd(fmas,v:__enumKey()) endif next ? (seconds()-nsec)*1000 // 437 mc тут побыстрее будет А еще быстрее можно сделать выборку ? ;)
|
|
|
|
| Администратор
|
Пост N: 2771
Зарегистрирован: 23.05.05
|
|
Отправлено: 20.03.13 19:16. Заголовок: Dima пишет: А еще б..
Dima пишет: цитата: | А еще быстрее можно сделать выборку ? ;) |
| Можно перевернуть хеш. То есть, в качестве ключа использовать kmkod, а вместо значения - массив {{recno(), kod_kl, codn}, ...} Если нужны только номера записей, можно добавлять только recno() примерно так: hmas:={=>} // разверну для ясности dbeval go top while ! eof() hmas[kmcod] := {} AADD(hmas[kmcod], {recno(), kod_kl, codn}) // или AADD(hmas[kmcod], recno()) skip enddo Тогда значением hmas[3] будет массив с номерами записей.
|
|
|
|
| |
Пост N: 2821
Зарегистрирован: 17.05.05
|
|
Отправлено: 20.03.13 19:29. Заголовок: Pasha Да но KMCOD н..
Pasha Да но KMCOD на разных записях может быть одинаковый , поэтому так не годится. Смысл затеи прост. Из заполненного hash массива быстро выбрать нужные Recno() и сложить в массив. Например нужно выбрать всех клиентов у которых код торгового агента KMCOD равен 5 или скажем выбрать всех клиентов у которых код группы CODGR равен 7. Хотелось сделать универсальный хэш массив (для разного рода выборок для фильтра) и такой массив я как бы создал но поиск по нему оставляет желать лучшего по времени. Хотя результат 500 мс для размера массива 700 000 записей тоже не плох. Имея массив с номерами записей BM фильтр ставится в лет. Сейчас такой массив записей я заполняю иначе (юзаю нужный ордер и заполняю массив). Думалось что с хэш массивом будет быстрее так как не надо лишний раз дергать базу.
|
|
|
|
| Администратор
|
Пост N: 2772
Зарегистрирован: 23.05.05
|
|
Отправлено: 20.03.13 19:35. Заголовок: Dima пишет: Да но K..
Dima пишет: цитата: | Да но KMCOD на разных записях может быть одинаковый , поэтому так не годится. |
| Как раз именно так и годится. Значением hmas[kmcod] будет не один номер записи, а массив recno(). И поиск в этом hmas по значению kmkod будет мгновенным. А одним хеш для всех случаев не обойдешься. Если выборки нужны по нескольким параметрам, то надо и делать несколько хеш-массивов, каждый для своего случая. Смысл использования хеш только в мгновенном поиске. Использовать хеш, чтобы затем делать цикл по нему для поиска бессмыссленно.
|
|
|
|
| Администратор
|
Пост N: 2773
Зарегистрирован: 23.05.05
|
|
Отправлено: 20.03.13 19:40. Заголовок: Дима, если работать ..
Дима, если работать с хеш непривычно, я могу выложить свои функции для отсортированных массивов. Мне надо только причесать свой код, тот вариант, что я выкладывал раньше, не сохранился. Суть примерно та же, что и хеш, только выглядит несколько нагляднее. К тому же, как выяснилось, при добавлении в хеш по умолчанию не оптимизировано выделение памяти. А у AADD с этим все в порядке.
|
|
|
|
| |
Пост N: 2822
Зарегистрирован: 17.05.05
|
|
Отправлено: 20.03.13 19:41. Заголовок: Pasha пишет: Смысл ..
Pasha пишет: цитата: | Смысл использования хеш только в мгновенном поиске. Использовать хеш, чтобы затем делать цикл по нему для поиска бессмыссленно. |
| Это я уже понял и подумаю над твоей идеей. Спасибо Pasha пишет: цитата: | Если нужны только номера записей, можно добавлять только recno() |
| Да я это понял. Спасибо. Обдумываю.
|
|
|
|
| |
Пост N: 2823
Зарегистрирован: 17.05.05
|
|
Отправлено: 20.03.13 19:44. Заголовок: Pasha пишет: К тому..
Pasha пишет: цитата: | К тому же, как выяснилось, при добавлении в хеш по умолчанию не оптимизировано выделение памяти |
| я пока делаю так hb_hAllocate( hms, Lastrec() ) и все нормально по скорости добавления. Pasha пишет: цитата: | Дима, если работать с хеш непривычно, я могу выложить свои функции для отсортированных массивов. Мне надо только причесать свой код, тот вариант, что я выкладывал раньше, не сохранился. |
| Было бы не плохо и это сильно и не горит , хочу еще сам поиграться с хеш массивами.
|
|
|
|
| постоянный участник
|
Пост N: 173
Зарегистрирован: 17.02.12
|
|
Отправлено: 20.03.13 21:09. Заголовок: Pasha пишет:тот вари..
|
|
|
|
| |
Пост N: 2824
Зарегистрирован: 17.05.05
|
|
Отправлено: 20.03.13 21:30. Заголовок: Pasha пишет: тот ва..
Pasha пишет: цитата: | тот вариант, что я выкладывал раньше, не сохранился. |
| да он где то есть на форуме я не давно натыкался на эту тему , нужно пошукать немного.
|
|
|
|
| постоянный участник
|
Пост N: 174
Зарегистрирован: 17.02.12
|
|
Отправлено: 20.03.13 21:38. Заголовок: Pasha пишет:А одним ..
Pasha пишет: цитата: | А одним хеш для всех случаев не обойдешься. Если выборки нужны по нескольким параметрам, то надо и делать несколько хеш-массивов, каждый для своего случая. |
| Как это будет выглядеть применительно к Leto ? "несколько хеш-массивов" надо пополнять или создавать заново ? С предложенным способом от Dima понятно, при загрузке программы создал такой hash и работаю, на клиенте относительно него, пополняя его при LastRec > len(hmas) до потери пульса.
|
|
|
|
|
| |
Пост N: 2826
Зарегистрирован: 17.05.05
|
|
Отправлено: 20.03.13 22:24. Заголовок: SergKis пишет: попо..
SergKis пишет: цитата: | пополняя его при LastRec > len(hmas) до потери пульса |
| И меня та же идея посещала , но LETO пока не юзаю (поигрался малость - ПОНРАВИЛОСЬ) и перевожу прогу с Clipper на Harbour CDX а потом будет и LETO и вопросов будет видимо много. Ты еще не забывай что такой массив еще нужно корректировать и иметь реакцию на удаление записей с учетом что все это может происходить в сети ;) Вообще при таком подходе либо держать нужно кучку hash массивов и юзать BM фильтра или иметь такую же кучку дополнительных индексов (тегов) и юзать SCOPE. И там и там есть свои и плюсы и минусы , в прочем это смотря какая задача и как все там организовано. На вкус и цвет как говорится , товарищей нет SergKis пишет: цитата: | пополняя его при LastRec > len(hmas) до потери пульса |
| Как славно что не нужно делать вот такой проверки , да и хэш массивов нет в clipper;) if len(hmas)<4096 else endif
|
|
|
|
| постоянный участник
|
Пост N: 175
Зарегистрирован: 17.02.12
|
|
Отправлено: 21.03.13 08:20. Заголовок: Dima пишет:Вообще пр..
Dima пишет: цитата: | Вообще при таком подходе либо держать нужно кучку hash массивов |
| Проще работать с dbf MemIO или даже локальным dbf с полями, обеспечивающими быстрый доступ для создания нужных tag-ов и для переключения просмотров browse. С таблицей сервера relation по recno. Для обеспечения секретности можно поля обезличить (типа R_1,R_2,...) или что-то еще. Сейчас через MemIO примерно так делаем, только не весь dbf, а через запросы. Тоже пока без сервера- процесс перевода с Clipper на cdx в разгаре, потом Leto. Dima пишет: цитата: | Ты еще не забывай что такой массив еще нужно корректировать и иметь реакцию на удаление записей с учетом что все это может происходить в сети ;) |
| В локальном dbf все записи, с учетом удаленных и только ключевые, не изменяемые поля. На сервере можно включит триггер, заполняющий поле типа TimeStamp (или символьное DtoS(Date())+StrTran(Time(), ":", "")+right(hb_ntos(bk_MilliSeconds()), 3)), для запросов по изменениям ...
|
|
|
|
| Администратор
|
Пост N: 2775
Зарегистрирован: 23.05.05
|
|
Отправлено: 21.03.13 10:04. Заголовок: SergKis пишет: Как ..
SergKis пишет: цитата: | Как это будет выглядеть применительно к Leto ? |
| Если использовать Leto, то надо возложить функцию формирования bm-фильтра на сервер. Зачем гонять данные с сервера на клиент, формировать на клиенте массив с номерами записей и затем гнать обратно этот массив на сервер ? Зачем тогда такой сервер нужен ? Сейчас в BMDBF* по set filter массив с номерами записей и так формируется, но это делается без учета scope. Можно исправить этот недостаток. Я вижу 3 пути для этого: 1) Убедить харбор-сообщество сделать это прямо в харборе (пока не получилось). 2) Скопировать сырцы BMDBF* в letodb и внести в них нужные изменения. 3) Сделать в letodb rdd - наследника BMDBF* и переписать в нем метод SetFilter (это сложнее). Ну и наконец, можно на сервере просто добавить функцию, которой вы передавались параметры: имя тэга, scope, filter, и эта функция сама бы формировала bm-фильтр по этим данным
|
|
|
|
| |
Пост N: 2830
Зарегистрирован: 17.05.05
|
|
Отправлено: 21.03.13 10:18. Заголовок: Pasha Поддерживаю в..
Pasha Поддерживаю вариант 2 и "можно на сервере просто добавить функцию"
|
|
|
|
| постоянный участник
|
Пост N: 177
Зарегистрирован: 17.02.12
|
|
Отправлено: 21.03.13 11:08. Заголовок: Dima пишет:Поддержив..
Dima пишет: цитата: | Поддерживаю вариант 2 и "можно на сервере просто добавить функцию" |
| Тоже
|
|
|
|
| постоянный участник
|
Пост N: 178
Зарегистрирован: 17.02.12
|
|
Отправлено: 21.03.13 11:34. Заголовок: Pasha пишет:Ну и нак..
Pasha пишет: цитата: | Ну и наконец, можно на сервере просто добавить функцию, которой вы передавались параметры: имя тэга, scope, filter, и эта функция сама бы формировала bm-фильтр по этим данным |
| Можно было бы обойтись этим, но тогда If rddname() == 'LETO' leto_setBmFilter(Tag,Scopr,Filter) Else dbSetFilter(...) Endif тоже как то ...
|
|
|
|
| Администратор
|
Пост N: 2778
Зарегистрирован: 23.05.05
|
|
Отправлено: 21.03.13 21:59. Заголовок: Добавил на сервере l..
Добавил на сервере letodb функцию LBM_DbSetFilter Вызов функции с клиента: leto_ParseRec( leto_Udf('LBM_DbSetFilter', <xScope>, <xScopeBottom>, <xOrder>, <cFilter>, <lDeleted> ) ) Функция устанавливает bitmap-фильтр по условиям scope, filter, и возвращает буфер с первой записью, удовлетворяющей условию фильтра
|
|
|
|
| |
Пост N: 2858
Зарегистрирован: 17.05.05
|
|
Отправлено: 22.03.13 22:02. Заголовок: Pasha пишет: LBM_D..
Pasha пишет: проясни плиз. если активным является ордер 2 , но в LBM_DbSetFilter я указал xOrder равным 5 , какой ордер будет активным после установки LBM_DbSetFilter ? Должен быть 2 , что то не увидел я в сырцах возврата на прежний индекс после установки LBM_DbSetFilter. Сейчас я ставлю простой фильтр когда SCOPETOP и SCOPEBOTTOM равны вот так. Прежний ордер остается на месте в любом случае после выполнения XbmFilter. func XbmFilter(nseaord,xsea,myblock) local ret:=.t. local old_ord:=indexord() local old_rec:=recno() local afilt:={} default myblock to nil dbclearfilter() dbsetorder(nseaord) if dbseek(xsea) dbOrderInfo(DBOI_SCOPEBOTTOM,,, xsea) dbeval({|| aadd(afilt,recno())},myblock,,,,.t.) dbOrderInfo(DBOI_SCOPEBOTTOMCLEAR) endif dbsetorder(old_ord) if len(afilt)>0 BM_DBSETFILTERARRAY(afilt) go top else ret:=.f. dbgoto(old_rec) endif return ret
|
|
|
|
| Администратор
|
Пост N: 2783
Зарегистрирован: 23.05.05
|
|
Отправлено: 23.03.13 01:06. Заголовок: На сервере нет инфор..
На сервере нет информации о том, какой управляющий индекс у клиента. Поэтому в каждой команде, которая поступает с клиента (для которой это конечно необходимо), должен быть прямо указан индекс. Следовательно, серверу нет необходимости возвращать прежний индекс. Поэтому не должно быть такой ситуации, когда управляющий индекс на клиенте один, а LBM_DbSetFilter получает другой. Чтобы избежать этого, я на клиенте добавил функцию, у которой всего 3 параметра: LBM_DbSetFilter( <xScope>, <xScopeBottom>, <cFilter> ) При этом серверу автоматически передается текущий индекс.
|
|
|
Ответов - 44
, стр:
1
2
3
All
[только новые]
|
|