"Есть такой, совсем маленький, цикл, ничего особенного. Пробегает по нему почти нормально, но на последнем проходе тормозит минуты на 2, наверное..." (Марат) или о том, что женщине ничто не мешает быть Монстром Аксесса :))
Marat 03.07.2001
Прочтение рекордсета... Есть такой, совсем маленький, цикл:
Do Until rst.EOF strResult = strResult & ", " & Mid(rst.Fields(strField), 1, 3) & Mid(rst.Fields(strField), 11) rst.MoveNext Loop
Ничего особенного. Пробегает по нему почти нормально,но на последнем проходе тормозит минуты на 2, наверное. И потом идет дальше, как будто ничего и не было.
Windows NT, Access 97, английские версии
Федор 03.07.2001
1. Попробуйте While not rst.eof
While not rst.eof почему-то работает лучше и точно захватит последнюю запись. В вашем примере, по-моему, последняя запись (перед eof) не обрабатывается.
2.А что значит - НА ПОСЛЕДНЕМ ПРОХОДЕ? На последней записи или что?
Marat 03.07.2001
Да нет, последняя запись обрабатывается. Просто,когда запускаю функциё, такое ощущение, что Аксесс зависает. Когда прохожу в отладке по F8, указатель (желтый) бегает по циклу, но когда доходит до последней записи, на переходе на "Loop" в последний раз, происходит эта "заморозка". Чем последняя запись отличается от остальных-то?... Риторический вопрос…
silich 04.07.2001
Может быть Аксесс не верит, что он на последней записи и решает пройти ещё раз весь цикл?? :)) бредовая идея, но мне нравится ;))
Федор 04.07.2001
Промоделировал ситуацию - у меня этого нет А у вас случайно не в сети работает? С каким-нибудь MS SQL-Server? тогда это возможно.
Marat 05.07.2001
Я подобные вещи много раз делал, никогда такого не было. SQL-Server не используется, только разделенная база Аксесс, данные сидят на сервере.
Ольга 04.07.2001
Может быть так... Если данные гоняются по сети, то на клиента они поступают порциями, сегментами. Чтобы обнаружить EOF, клиенту надо просмотреть все данные таблицы (получая их этими порциями). Если так сложилось, что все обусловленные выборкой записи находятся в начальном(ых) сегменте, то пока будут считываться остальные N сегментов данных до EOF, будет пауза :( Access же не знает, что эта запись последняя по этому условию и больше ничего нет :(
Если сделать ORDER BY, то пауза должна быть в начале цикла :) Т.к. чтобы отсортировать, надо сначала всё прокачать.
Если пауза такая заметная, то м.б. попробовать построить индекс по полям условия выборки. Тогда Access должен бы сообразить и искать EOF по данным условиям по этому индексу, т.е. определить быстрее (по смене значения индекса, не просматривая всЁ).
Смоделировать такую заметную паузу мне, правда, не удалось. Возможно, нужны бОльшие объемы данных и траффик…
Marat 05.07.2001
Re: Может быть так... Я думаю - нет. Кажется, Аксесс извлекает рекордсет сначала, формирует его в готовую табличку, а потом только начинает бегать. Можно это в дебуггере отследить. Но может я из-за своей темности что-то не так понимаю? Может ,действительно, стоит попробовать с ORDER BY, если это изменит положение дел, то тогда ты права. С индексами - это правильно. Действительно, я их как-то мало использую. Кстати, больших объемов нет, но может быть траффик. Объемы маленькие, т.к. База только создается, и в ней данных чуть, только для примера…
Ольга 06.07.2001
Если объемы небольшие, то тогда эта пауза не понятна, конечно... А вот то, что сначала готовится RecordSet, а потом обработка, я что-то не согласна. Когда открывается RS большого объема, напр., в таблицу формы, то на экране (в таблице) уже видны данные (!), и их можно, например, листать, а счетчик записей внизу еще "бежит", т.е. RS еще не весь. Разве не так?..
А с ORDER BY проверь ради интереса. У меня такая пауза никак не получилась, чтобы проверить. Т.е. предположение-то теоретическое :( А, может, это я такая тёмная :)
Ольга 06.07.2001
Марату - Всё-таки Это так. Ну, вот мне и удалось получить заметную паузу (не минуты, но неск.секунд. Достаточно заметно). Теперь это не теоретические предположения. Все проверила.
Set rst = CurrentDb.OpenRecordset _ ("SELECT * FROM TTT WHERE name1='OOO' ") strResult = "" For i = 1 To 2
Do Until rst.EOF strResult = strResult & rst!ID & Chr(13) rst.MoveNext Loop
rst.MoveFirst Next i
MsgBox (strResult) rst.Close
Таблица ТТТ – связанная, находится в БД .mdb на сервере. 17000 записей. Траффик из себя одной мне было создать трудно, насоздавала побольше записей. Думаю, при траффике и/или большом объеме одной записи (много текстовых полей) результат будет тот же.
Проходим код по F8 (иначе, действительно, трудно заметить эту паузу).
Цикл “For i” показывает разные временные задержки на 1-ом и 2-ом проходе!
Эксперименты. 1. Запись, подходящая условию name1=’OOO’, всего ОДНА и находится в начале таблицы (3-ья).
На OpenRecordset практически нет паузы, только едва заметная на собственно создание запроса.
Первый проход RecordSet`a (в цикле по i). На Loop после получения 1-ой нужной записи – ПАУЗА (ищется следующая до конца таблицы, пока не обнаруживается EOF).
Второй проход RecordSet`a (в цикле по i). Никаких задержек нет – весь RecordSet уже сформирован и на клиенте.
2. Записей, подходящих условию name1=’OOO’, - ДВЕ –одна находится в начале таблицы (3-ья), другая в самом конце таблицы (16998-я, т.е. перед EOF).
На OpenRecordset практически нет паузы, только едва заметная на собственно создание запроса.
Первый проход RecordSet`a (в цикле по i). На Loop после получения 1-ой нужной записи – ПАУЗА (ищется следующая, а она в самом конце).
На Loop после получения 2-ой нужной записи – паузы нет! (ищется следующая до конца таблицы, а это уже рядом).
Второй проход RecordSet`a (в цикле по i). Никаких задержек нет – весь RecordSet уже сформирован и на клиенте.
Добавляем в запрос - ORDER BY Set rst = CurrentDb.OpenRecordset _ ("SELECT * FROM TTT WHERE name1='OOO' ORDER BY name1")
3. Вся задержка (ПАУЗА) приходится на OpenRecordset. Т.е. к началу цикла For все данные уже на клиенте, Recordset сформирован. На Loop`ах пауз нет.
Строим индекс на поле name1. (Построить его можно только непосредственно в таблице в БД на сервере, с этим, наверное, могут быть проблемы с правами?)
4. Вся задержка (ПАУЗА) приходится на OpenRecordset. С ORDER BY пауза, естественно, больше.
5. При сравнении работы с индексом (без ORDER BY) и без индекса с сортировкой (c ORDER BY) – с индексом работает быстрее (задержка при OpenRecordset меньше). ----------- Таким образом, откуда пауза, понятно.
При отсутствии какой бы то ни было сортировки (ORDER BY или индекса) данные на клиента подкачиваются по мере надобности (во время обработки). В зависимости от равномерности расположения в таблице запрошенных данных возникают эти паузы.
Если запрошены отсортированные (ORDER BY) данные, то они должны быть отсортированы до начала обработки, т.е. сразу при открытии RecordSet`a (все перекачиваются, сортируются и отдаются).
Механизм работы индексов в Access мне неизвестен :( Но можно предположить (опять :), что в начале на клиента перекачивается некая структура с индексом и потом по нему перекачиваются только нужные данные. Так должно бы быть. Тогда при больших объемах данных и незначительной выборке из них он очень поможет. А как на самом деле, я не знаю. В любом случае индекс должен сокращать время доступа, иначе на кой он нужОн ;) Не только же для констрейнтов на уникальность…
Ну, вот. По-моему, кое-что с паузами прояснилось.
Marat 06.07.2001
Забила мозгами, я плачу, иду в угол, стою там полчаса :))