Фильтр таблицы в гриде по нескольким полям, по сети жутко тормозит.

А. С.
Дата: 08.12.2012 11:17:50
Коллеги, я в растерянности.
Есть таблица, простая, с полями Город (Town), Улица (Ul), Дом (Dom), Квартира (Kv). Все поля текстовые.
Есть форма с гридом, куда все это выводится.
В таблице порядка 50 тыс записей.
В этой же форме для поиска есть 2 Combobox с уникальными значениями городов и улиц и 2 TextBox для ввода дома и квартиры.
При заполнении критериев для поиска выполняю простой фильтр, в зависимости от заполненных значений.
То есть. Либо только по городу, либо только по дому, либо по городу и по дому, короче различные комбинации.
set filter to allt(dom)=allt(thisform.dom.value) and allt(kv)=allt(thisform.kv.value)
set filter to ul=thisform.ul.value and allt(dom)=allt(thisform.dom.value) and allt(kv)=allt(thisform.kv.value)


Локально или по сети, если монопольно (или 1 пользователь) все летает прекрасно.
Как только несколько пользователей - то жутко тормозит по сети.
Дело даже не в том, что фильтрует долго, после фильтра даже привисает при переходе на другие записи.

Отслеживаю мониторами разными, показывает трафик достаточно большой при фильтровании и смене записей. То есть каждый клик по строкам сопровождается качанием с сервера части таблицы.

Как мне оптимизировать фильтр?
Думаю сделать составной индекс по полям, но не придумаю как потом по нему искать.
Jonny540
Дата: 08.12.2012 11:39:36
А. С.,

Делай вместо фильтров выборки в курсоры и на локальной машине работай с этими курсорами.
А. С.
Дата: 08.12.2012 13:42:20
Как вариант да. Но мне в процессе работы надо там видеть изменения, которые другие пользователи вносят.
Dima T
Дата: 08.12.2012 20:36:55
А. С.
Как вариант да. Но мне в процессе работы надо там видеть изменения, которые другие пользователи вносят.

И что может постоянно меняться? Город, Улица, Дом, Квартира?

Используй курсорадаптер. Для обновления у него есть метод RecordRefresh()
А. С.
Дата: 09.12.2012 12:29:23
Это я для примера написал, там в реале полей больше. Добавляются новые к тому же.
Pulsar_p
Дата: 09.12.2012 13:40:51
А. С.,
У меня самого подобная задача, только записей в основной таблице в несколько раз больше (если брать суммарно по таблицам>1 000000 записей), полей за сотню, а пользователей, одновременно работающих с базой, не один десяток. Использовать "set filter to" в такой ситуации очень, очень плохая идея, потому как получаются жуткие тормоза. Я в своем большом приложении не использую эту установку ни разу: и дело не только в том, что тормозит (на маленьких объемах информации может и нет), а в том, что где-нибудь забудешь снять этот фильтр, потом намучаешься, и не все операторы берут во внимание эту установку... Плавали, знаем. Jonny540 прав, "Делай вместо фильтров выборки в курсоры и на локальной машине работай с этими курсорами." Я так и поступаю, мне кажется, это самый оптимальный путь. Во-всяком случае, 1 или 20 пользователей одновременно работают с базой, по скорости обработки данных существенной разницы нет. Понятно, что переделывать приложение довольно трудная задача, но если хочешь избавиться от "тормозов" и других проблем, ИМХО, другого пути нет.
reware
Дата: 09.12.2012 21:03:13
А. С.
Коллеги, я в растерянности.
Есть таблица, простая, с полями Город (Town), Улица (Ul), Дом (Dom), Квартира (Kv). Все поля текстовые.
<skipped>

Локально или по сети, если монопольно (или 1 пользователь) все летает прекрасно.
Как только несколько пользователей - то жутко тормозит по сети.

<skipped>

Как мне оптимизировать фильтр?
Думаю сделать составной индекс по полям, но не придумаю как потом по нему искать.

Да не надо индексов. Надо использовать SELECT-SQL. Если обьяснять на пальцах (правда их всего 10), то SET FILTER тупо сканирует сверху вниз всю таблицу и, будучи на будущее оставленным включенным, так и будет это делать при каждом поползновении юзера. Хорошо для маленьких таблиц. Я бы советовал (записей 50000, если я не забыл) использовать
SELECT town, street, house, flat, recno() AS recn FROM MyTable INTO TABLE NewTable

В результате получаешь таблицу NewTable c полями town, street, house, flat и recn. В поле recn хранится номер recno() родимой единоутробной таблицы, откуда сделан селект. Все поля (кроме recn) можешь редактировать. И, кстати, не понятно было - изменения, внесённые в выборку должны попасть и в материнскую таблицу ? Допустим, да.
Тогда так - без всяких индексаций берём из NewTable значение recn и по нему делаем GO NewTable->recn IN MyTable. И все дела, мы стоим на нужной записи в MyTable, можно в ней править поля значениями из NewTable.

SELECT NewTable
GO TOP
DO WHILE !EOF()
     SELECT MyTable
     GO NewTable->recn
     REPLACE town WITH NewTable->town, street WITH  NewTable->street,  ;
                  house   WITH   NewTable->house, flat WITH NewTable->flat
     SELECT NewTable
     SKIP
ENDDO


После всех изощрений сильно рекомендуется удалить временную таблицу NewTable (закрыв её, если открыта)
ERASE NewTable.dbf
А. С.
Дата: 10.12.2012 23:45:09
Да, так и сделал, спасибо.
Встречный вопрос, просто ради любопытства.
Если я простые индексы сделаю на все эти поля, это ускорит выборку Select-SQL?
AndreTM
Дата: 10.12.2012 23:57:34
Индексы в данном случае не нужны.
Указанный SELECT их не использует (нет никаких условий в выборке), а GO индекс не требуется - в Фоксе это простой арифметический расчет физического положения записи.
Penner
Дата: 11.12.2012 13:33:01
Index + Set Key