Страница 1 из 1
Контекстный поиск в списке
Добавлено: 18 Ноябрь 2014, 13:03
Игорь Столяров
Привет всем !
Хотел обсудить тему, можно ли как-то ускорить контекстный поиск в LIST по строке.
Мы сейчас просто добавляем в фильтр LIST строку:
Код: Выделить всё
Loc:FindString CString(21)
~Loc:FindString Or InString(Loc:FindString,Upper(Clip(SPI:Field01) & Clip(SPI:Field02)),1)
Все прекрасно работает ... но на больших списках тормозит, особо в сети ...

Можно ли как-то алгоритмически оптимизировать такой фильтр ?
Заранее спасибо за любые идеи (если они здесь вообще возможны).
P/S: SQL запрос не предлагать, БД - TPS ...

Re: Контекстный поиск в списке
Добавлено: 18 Ноябрь 2014, 13:32
Shur
Что если закэшировать таблицу-список в памяти при помощи In-Memory драйвера? В принципе тогда поиск может ускориться.
Или, если под рукой этого драйвера нет или он не используется в этом проекте, то банально считать список в очередь, и затем поиск осуществлять в ней.
Re: Контекстный поиск в списке
Добавлено: 18 Ноябрь 2014, 13:43
Игорь Столяров
Да, безусловно поиск в таблице In-Memory будет очень быстрый, но ...
это ведь надо большой список при открытии LIST загрузить в память.
Получается глупая ситуация: мы не знаем, будет или нет юзер вообще
использоваться поиск, но при открытии LIST тратим много времени
на загрузку этого списка ...

К тому же такой вариант не совсем
удобен при модификации списка ...
По оптимизацией я все-таки подразумевал другие варианты строки фильтра.
Re: Контекстный поиск в списке
Добавлено: 18 Ноябрь 2014, 15:30
kreator
А если посмотреть в сторону match и BrowseFuzzyMatching control. Я где-то слышал, что быстрая функция. Хотя, наверно, чудес не бывает. Кстати, и SQL быстр во многом из-за того, что держит данные в оперативной памяти.
Re: Контекстный поиск в списке
Добавлено: 19 Ноябрь 2014, 14:12
Shur
Как ускорить поиск в списке по подстроке алгоритмически? Могу предложить вариант для рассмотрения, в котором сканирование всей таблицы может быть заменено на поиск по индексу.
Но требует подготовки и постоянного обслуживания.
Допустим имеем исходную таблицу c полями ID, Str. Строим вспомогательную таблицу T с такими же полями (ID,Str), в которую запишем ID и хвосты от Str:
ID,substr(Str,1,len(Str))
ID,substr(Str,2,len(Str)-1)
и т.д. для всех записей оригинальной таблицы.
Далее делаем индекс By_StrTail по второму полю и осуществляем поиск нужной нам строки Loc:FindString по индексу:
T:Str = Loc:FindString
set(T:By_StrTail,T:By_StrTail).
loop... next(T)... end
Осталось только оставить уникальные ID и выдать по ним соответствующий список из оригинальной таблицы.
Re: Контекстный поиск в списке
Добавлено: 19 Ноябрь 2014, 14:52
Игорь Столяров
Математически красиво.

Но на практике, например, для каждой записи с зоной поиска в 1KByte,
мы получим 1024 записи в индексном файле (т.е. 1 MByte) + сам ключ поиска.
Даже для статичных списков - сомнительно. А при модификации или удалении
одной записи - мы должны будем проверить и обработать 1024 записи в индексном
файле. К тому же полностью меняет алгоритмику запроса на поиск, уже получается,
что-то близкое к SQL запросу и визуализации его результата. Жесть !
Сейчас хочу промерить поиск с использованием BINDEXPRESSION(), может быть это даст выигрыш по времени ...
Re: Контекстный поиск в списке
Добавлено: 20 Ноябрь 2014, 16:08
Shur
Это оценка объёма сверху.
Но всё может оказаться не так уж плохо.
Если исходить из длины локатора Loc:FindString (предположим, 20 символов (@s20)),
то можно во вспомогательную таблицу вставлять хвосты длиной 20 символов:
ID,substr(Str,1,size(Loc:FindString))
ID,substr(Str,2,size(Loc:FindString))
Эффект будет более чем заметным -- уменьшение вспомогательной таблицы примерно в 50 раз.
Re: Контекстный поиск в списке
Добавлено: 20 Ноябрь 2014, 16:43
Дед Пахом
Да 20 тоже много, 5-10 в самый раз.