Постраничный вывод в ADO. Что это и как с ним работать?
От: mihauzen Украина  
Дата: 17.02.04 17:30
Оценка:
Всем приветы!

Объясните, пожалуйста, что такое постраничный вывод в АДО, как он работает, как им пользоватья и управлять. Я читал, что для этого используются свойства Recordset PageSize, PageCount, AbsolutePage. Что такое PageSize — понятно. PageCount — написано, указывает, сколько страниц находится в наборе записей с учетом свойства PageSize. Следовательно, получив Recordset первого запроса я могу узнать сколько всего у меня страниц в наборе записей. А эти наборы записей где-то храняться?
Потом, когда я перемещаюсь по Recoreset и достиагаю его конца или начала, при этом, данная страница, допустим, где-то из середины набора записей, то каким образом мне подгрузить, допустим, еще N записей < PageSize, т.е. другими словами, как осуществить прокрутку данных в моем Recordset на заданное количество записей и кто их подгрузит в Recordset?
...все это временно... (с) Айэм
Re: Постраничный вывод в ADO. Что это и как с ним работать?
От: mihauzen Украина  
Дата: 18.02.04 16:45
Оценка:
Здравствуйте, mihauzen, Вы писали:

M>Всем приветы!


M>Объясните, пожалуйста, что такое постраничный вывод в АДО, как он работает, как им пользоватья и управлять. Я читал, что для этого используются свойства Recordset PageSize, PageCount, AbsolutePage. Что такое PageSize — понятно. PageCount — написано, указывает, сколько страниц находится в наборе записей с учетом свойства PageSize. Следовательно, получив Recordset первого запроса я могу узнать сколько всего у меня страниц в наборе записей. А эти наборы записей где-то храняться?

M>Потом, когда я перемещаюсь по Recoreset и достиагаю его конца или начала, при этом, данная страница, допустим, где-то из середины набора записей, то каким образом мне подгрузить, допустим, еще N записей < PageSize, т.е. другими словами, как осуществить прокрутку данных в моем Recordset на заданное количество записей и кто их подгрузит в Recordset?

Нашел еще однин очень интересный метод, и хоть он немного оф-топ, но...
У меня стояла следующая задача: необходимо, что бы в памяти машины в каждый момент хранилась только та информвция, т.е. только столько записей результирующего recordset'a, сколько можно отобразить на экране заданного размера. Я думал для этой цели использовать страницы и постраничный вывод. Но, нашел такое свойство, как CasheSize и MaxRecords. И, если я правильно понимаю, присвоив им определенное значение (СasheSize = MaxRecords = N), в памяти компьютера будет храниться количество записей не большее N. И если результат запроса будет больше, чем N, то навигируя по имеющимся в Recordsete N записям и переходя на за придел N, АДО обеспечит подгрузку новых записей из результирующего количества, которые не вошли в, скажем, первое N. Я парвильно понимаю или нет? Поправьте, пожалуйста, если что не так...
...все это временно... (с) Айэм
Re[2]: Бррр....
От: Merle Австрия http://rsdn.ru
Дата: 19.02.04 10:13
Оценка:
Здравствуйте, mihauzen, Вы писали:

M>> А эти наборы записей где-то храняться?

Ну, строго говоря, это зависит от типа курсора, с которым открыт рекордсет. Клиентский — на клиенте, серверный — на сервере.
При серверном типе курсора пользуются недокументированные хранимки, типа sp_cursoropen... Очевидно, постраничный вывод реализован с помощю курсора, но подробностей не знаю...

M>> т.е. другими словами, как осуществить прокрутку данных в моем Recordset на заданное количество записей и кто их подгрузит в Recordset?

Например, заданием свойства .AbsolutePage у рекордсета, ADO и подгрузит.

M>У меня стояла следующая задача: необходимо, что бы в памяти машины в каждый момент хранилась только та информвция, т.е. только столько записей результирующего recordset'a, сколько можно отобразить на экране заданного размера.

Ну и забирай ее с сервера ровно столько, либо через ADO'шный paging с серверным курсором, либо вообще явно ограничив выборку.

M>Но, нашел такое свойство, как CasheSize и MaxRecords.

CacheSize довольно хитрый параметр и лучше с ним не играться...
И к чему такое требование к количеству записей на клиенте?
Мы уже победили, просто это еще не так заметно...
Re[3]: Бррр....
От: sam11 Россия http://sam.0n.ru
Дата: 19.02.04 12:21
Оценка:
>>... серверный — на сервере. При серверном типе курсора пользуются недокументированные хранимки, типа sp_cursoropen... Очевидно, постраничный вывод реализован с помощю курсора, но подробностей не знаю...

А хотелось бы поподробнее насчет серверных курсоров и постраничном выводе.
Re[4]: Бррр....
От: Merle Австрия http://rsdn.ru
Дата: 19.02.04 12:34
Оценка:
Здравствуйте, sam11, Вы писали:

S>А хотелось бы поподробнее насчет серверных курсоров и постраничном выводе.

А чего там подробнее? Хранимки эти недокументированы, поэтому официальной информации нет и принцип по которому они работают тоже непонятен, но не думаю, что там что-то новое. Скорее всего, это лишь вариация обычного курсора, заточеная под постраничный вывод, причем не шибко эффективная, судя по скорости с которой ADO этим занимается.
Поэтому если интересно — выход один: в одну руку берется простенький пример с постраничным выводом, в другую профайлер — и вперед, удовлетворять исследовательский зуд..
Мы уже победили, просто это еще не так заметно...
Re[3]: Бррр....
От: mihauzen Украина  
Дата: 19.02.04 14:01
Оценка:
Здравствуйте, Merle, Вы писали:

M>И к чему такое требование к количеству записей на клиенте?


Клиент — это многофункциональное мультимедийное приложение. Работа с базой — не основной аспект, поэтому, ради экономии памяти, а она, уже посчитано, будет кушаться очень хорошо на все остальные детали проекта, было решено держать в памяти только видимую информацию (то, что будет видно в таблице). Сейчас объясню механизм, который бы хотелось иметь.
Есть огромная база-базище. Если ей передать на выполнение запрос, то получим результат, тоже огромнейший. Понятно, что хранить такой объем информации в памяти не рационально. Представим, что результат гипотетически есть, т.е. сервер знает последовательность (нумерацию, как бы) записей результата, но памяти для всего объема результата не выделяет. Хочется, чтобы в памяти лежал только блок из N записей из этого(гипотетического)результата, а так же, что бы при навигации по этому блоку( а навигация происходит через прокрутку в таблице), в него автоматом помещались следующие/предыдущие, вообщем, видимые записи из общего результата,т.е. реально память держит N записей, которые видимы в таблице, и автоматом (или как?) эти N записей динамически обновляются новыми, которые попадают в поле видимости, а старые, соответственно, новыми замещает.

Но вот в чем возникает вопрос (т.к. я не имею опыта работы с БД):
1.Если рассмотреть ситуацию, когда результат запроса огромный. Что именно хранит в себе Recordset? Как я понял, это зависит от CasheSize(=1 по умолчанию). Т.е. по умолчанию в памяти клиента (в зависимости от курсора) Recordset хранит только одну запись, а остальной объем результата лежит в памяти на сервере (который в данном случае является этой же машиной). Я правильно понимаю?
2.Если 1-ое я понимаю правилньо, то как тогда заставить сервер хранить в памяти только заданное количество записей результата? Где-то я слышал, что это можно осуществить через SQL запрос(что-то через TOP N), при этом база должна иметь уникальное поле(ключ), относительно которого сервер и будет давать этот результат. Правильно ли я ронимаю и есть ли другие способы?
3.Если взять способ с SQL-запросом, тогда, как получить последний набор N записей или где-то из середины гипотетического результата, пока был обработам только запрос набора на первые N записей?
4.Может ли мне как-то помочь постраничный вывод и как?

Вообщем, вопросов может быть еще уйма. Ответь те, пожалуйста, хотябы на один: можно ли реализовать поставленную задачу и как, в какую сторону копать?
...все это временно... (с) Айэм
Re[4]: Бррр....
От: mihauzen Украина  
Дата: 19.02.04 14:18
Оценка:
Здравствуйте, mihauzen, Вы писали:

M>Здравствуйте, Merle, Вы писали:


M>>И к чему такое требование к количеству записей на клиенте?


M>Клиент — это многофункциональное мультимедийное приложение. Работа с базой — не основной аспект, поэтому, ради экономии памяти, а она, уже посчитано, будет кушаться очень хорошо на все остальные детали проекта, было решено держать в памяти только видимую информацию (то, что будет видно в таблице). Сейчас объясню механизм, который бы хотелось иметь.

M>Есть огромная база-базище. Если ей передать на выполнение запрос, то получим результат, тоже огромнейший. Понятно, что хранить такой объем информации в памяти не рационально. Представим, что результат гипотетически есть, т.е. сервер знает последовательность (нумерацию, как бы) записей результата, но памяти для всего объема результата не выделяет. Хочется, чтобы в памяти лежал только блок из N записей из этого(гипотетического)результата, а так же, что бы при навигации по этому блоку( а навигация происходит через прокрутку в таблице), в него автоматом помещались следующие/предыдущие, вообщем, видимые записи из общего результата,т.е. реально память держит N записей, которые видимы в таблице, и автоматом (или как?) эти N записей динамически обновляются новыми, которые попадают в поле видимости, а старые, соответственно, новыми замещает.

M>Но вот в чем возникает вопрос (т.к. я не имею опыта работы с БД):

M>1.Если рассмотреть ситуацию, когда результат запроса огромный. Что именно хранит в себе Recordset? Как я понял, это зависит от CasheSize(=1 по умолчанию). Т.е. по умолчанию в памяти клиента (в зависимости от курсора) Recordset хранит только одну запись, а остальной объем результата лежит в памяти на сервере (который в данном случае является этой же машиной). Я правильно понимаю?
M>2.Если 1-ое я понимаю правилньо, то как тогда заставить сервер хранить в памяти только заданное количество записей результата? Где-то я слышал, что это можно осуществить через SQL запрос(что-то через TOP N), при этом база должна иметь уникальное поле(ключ), относительно которого сервер и будет давать этот результат. Правильно ли я ронимаю и есть ли другие способы?
M>3.Если взять способ с SQL-запросом, тогда, как получить последний набор N записей или где-то из середины гипотетического результата, пока был обработам только запрос набора на первые N записей?
M>4.Может ли мне как-то помочь постраничный вывод и как?

M>Вообщем, вопросов может быть еще уйма. Ответь те, пожалуйста, хотябы на один: можно ли реализовать поставленную задачу и как, в какую сторону копать?


Небольшое дополнение к вопросу №1, которое, возможно, снимет часть остальных вопросов:
1'.Я посылаю серверу SQL запрос "select * ...". В результате, мне в Recordset(CasheSize=1) вернется первая найденная запись. Ищет ли сервер все остальные сразу, следовательно, тратит ли он память на их хранение, или следующую запись сервер найдет и передаст в Recordset с учетом запроса по одной из управляющих команд(MoveNext, MoveFirst, MoveLast)?
...все это временно... (с) Айэм
Re[5]: Бррр....
От: Аноним  
Дата: 19.02.04 14:23
Оценка:
Здравствуйте, Merle, Вы писали:

>> причем не шибко эффективная, судя по скорости с которой ADO этим занимается

Дело ведь не только в скорости. ADO работает на стороне клиента, а хотелось бы готовить самому данные на сервере и отдавать клиенту, потому как не всякий клиент может выполнить выборку типа
dataAdapter.Fill(dataSet1,1000,20,"InventoryItem")

>> ... в одну руку берется простенький пример
Простенький не годится. Там и постраничный то вывод можно через темповую таблицу сделать. Конечно, простыни листать никто не собирается. Но все же темповая таблица плохой выход в случае, когда нужны несколько первых страниц из большой выборки со слабым ограничением (фильтром).
>>... в другую профайлер
К сожалению, профайлер не ловит вызовы этих процедур, если пытаться сделать постраничную выборку через ADO

P.S. Слыхал я мнения, что процедурки эти (sp_cursoropen и sp_cursorfetch) работают намного быстрее стандартных средств работы с курсорами. Поэтому и хочется поподробнее узнать.
Re[4]: Бррр....
От: Merle Австрия http://rsdn.ru
Дата: 19.02.04 14:38
Оценка:
Здравствуйте, mihauzen, Вы писали:


M>Есть огромная база-базище. Если ей передать на выполнение запрос, то получим результат, тоже огромнейший. Понятно, что хранить такой объем информации в памяти не рационально.

Что за база?
Вообщем в любом случае, при условии, что база и приложение живут на одной машине — это утопия. Даже если получится заставить держать в памяти только маленький результат большой выборки, для того, чтобы сделать эту выборку, все равно потребуется память и много. SQL сервера к памяти вообще не равнодушны.
Если же база и приложение живут на разных машинах, то можно заставить сервер выдавать нужное количество записей из большой выборки.
Как это делается для конкретных серверов и общие принципы описаны здесь: http://www.rsdn.ru/article/db/identity.xml#XSLTPART145120120
Автор(ы): Иван Бодягин
Дата: 07.02.2004
Уникальная идентификация записей в таблице, является практически основой реляционных СУБД. Вообще в реляционной теории предполагается, что если две записи ни чем друг от друга не отличаются, то это явная избыточность, и количество таких записей можно сократить до одной. Собственно вопросам этой самой идентификации, каковых возникает на удивление много, и посвящен этот FAQ.


M>Но вот в чем возникает вопрос (т.к. я не имею опыта работы с БД):

M>1.Если рассмотреть ситуацию, когда результат запроса огромный. Что именно хранит в себе Recordset?
Зависит от типа этого рекордсета. Он может хранить информацию в БД, он может хранить ее на клиенте, от этого и зависит что именно и как.
Если я правильно помню CasheSize имеет смысл только для клиентских курсоров....

M>2.Если 1-ое я понимаю правилньо, то как тогда заставить сервер хранить в памяти только заданное количество записей результата? Где-то я слышал, что это можно осуществить через SQL запрос(что-то через TOP N), при этом база должна иметь уникальное поле(ключ), относительно которого сервер и будет давать этот результат. Правильно ли я ронимаю и есть ли другие способы?

Ну ссылочку выше я уже давал, там все написано...

M>4.Может ли мне как-то помочь постраничный вывод и как?

Может, если БД на другой машине. Если н аэтой же, то в любом случае надо отводить СУБД достаточно памяти, иначе это прямой путь к вечным тормозам.

M>Вообщем, вопросов может быть еще уйма. Ответь те, пожалуйста, хотябы на один: можно ли реализовать поставленную задачу и как, в какую сторону копать?

Хм, я бы копал в сторону ограничения размера всей выборки, в идеале, чтобы результат в принципе вмещался на одну страницу. Если неполучится, то искуственно ввел бы постраничный вывод за счет SQL'я.
Мы уже победили, просто это еще не так заметно...
Re[6]: Бррр....
От: Merle Австрия http://rsdn.ru
Дата: 19.02.04 14:49
Оценка:
Здравствуйте, Аноним, Вы писали:


А>Простенький не годится. Там и постраничный то вывод можно через темповую таблицу сделать. Конечно, простыни листать никто не собирается. Но все же темповая таблица плохой выход в случае, когда нужны несколько первых страниц из большой выборки со слабым ограничением (фильтром).

Почему плохой? вполне себе выход... Да и курсоры можно пользовать...
Вообщем это не есть большая проблема, в данном случае есть куча способов сделать это на сервере примерно с одинаковой производительностью.
http://www.rsdn.ru/article/db/identity.xml#XSLTPART145120120
Автор(ы): Иван Бодягин
Дата: 07.02.2004
Уникальная идентификация записей в таблице, является практически основой реляционных СУБД. Вообще в реляционной теории предполагается, что если две записи ни чем друг от друга не отличаются, то это явная избыточность, и количество таких записей можно сократить до одной. Собственно вопросам этой самой идентификации, каковых возникает на удивление много, и посвящен этот FAQ.


А>К сожалению, профайлер не ловит вызовы этих процедур, если пытаться сделать постраничную выборку через ADO

Хм... Где то я их ловил, но за давностью лет уже не помню, а копаться откровенно лень, потому как совершенно не интересно и никакой практической выгоды от этого поиметь нельзя.

А>P.S. Слыхал я мнения, что процедурки эти (sp_cursoropen и sp_cursorfetch) работают намного быстрее стандартных средств работы с курсорами.

Не а... Не быстрее, а где-то даже и медленнее, если я правильно помню.. Принципы-то одни и те же, и не думаю, чтобы они изобрели там что-то шибко хитрое.
Мы уже победили, просто это еще не так заметно...
Re[7]: Бррр....
От: sam11 Россия http://sam.0n.ru
Дата: 19.02.04 15:01
Оценка:
Спасибо за ссылку.
Самый лучший пэйджинг — это, конечно же, на MySql.
Limit MinRow,MaxRow

и вся любовь
Re[5]: Бррр....
От: mihauzen Украина  
Дата: 19.02.04 15:32
Оценка:
Здравствуйте, Merle, Вы писали:

M>Даже если получится заставить держать в памяти только маленький результат большой выборки, для того, чтобы сделать эту выборку, все равно потребуется память и много. SQL сервера к памяти вообще не равнодушны.


Т.е. мое дополнение к первому вопросу неверно. И сервер держит всю выборку в памяти, а возвращает только то, что потребуют конкретно?

M>>Вообщем, вопросов может быть еще уйма. Ответь те, пожалуйста, хотябы на один: можно ли реализовать поставленную задачу и как, в какую сторону копать?

M>Хм, я бы копал в сторону ограничения размера всей выборки, в идеале, чтобы результат в принципе вмещался на одну страницу. Если неполучится, то искуственно ввел бы постраничный вывод за счет SQL'я.
Ограничить результат выборки не представляю даже как. Допустим, это база телефонных номеров. По завпросу от пользователя нужно отобразить все, начинающиеся на 5. Результат будет огромным. Если считать ограничением добавление к этому запросу еще и условия, которое связано с текущим отображением и с тем, что нужно подгрузить еще, то описание такого условия... ...потребует не одного дня размышлений.
А, как искусственно ввести постраничный вывод за счет SQL, что это имеется ввиду?
...все это временно... (с) Айэм
Re[6]: Бррр....
От: Merle Австрия http://rsdn.ru
Дата: 19.02.04 15:44
Оценка: 3 (1)
Здравствуйте, mihauzen, Вы писали:

M>Т.е. мое дополнение к первому вопросу неверно. И сервер держит всю выборку в памяти, а возвращает только то, что потребуют конкретно?

Не совсем так.. В памяти сервера лежит много чего: блокировки, кеши страниц данных, узлы индексов, планы готовых запросов и так далее... Вообщем ему только дай, а он найдет подочто израсходовать...

M>Ограничить результат выборки не представляю даже как. Допустим, это база телефонных номеров. По завпросу от пользователя нужно отобразить все, начинающиеся на 5. Результат будет огромным.

А зачем ему все на 5? Реально он дальше второй страницы не уйдет.
Довольно часто получается подобрать условия таким образом, что надобность в постраничном просмотре вообще отпадает — это идеальный вариант.

M>А, как искусственно ввести постраничный вывод за счет SQL, что это имеется ввиду?

Ну я давал ссылку на FAQ, как раз на тот раздел где это описано..
Мы уже победили, просто это еще не так заметно...
Re[7]: Бррр....
От: mihauzen Украина  
Дата: 19.02.04 15:56
Оценка:
Здравствуйте, Merle, Вы писали:

M>>Ограничить результат выборки не представляю даже как. Допустим, это база телефонных номеров. По завпросу от пользователя нужно отобразить все, начинающиеся на 5. Результат будет огромным.

M>А зачем ему все на 5? Реально он дальше второй страницы не уйдет.
M>Довольно часто получается подобрать условия таким образом, что надобность в постраничном просмотре вообще отпадает — это идеальный вариант.
Это был просто пример. Реально, ситуации могут быть какими-угодно, и даже, может быть, необходимо будет давать наиболее полную информацию, а не ограничивать ее. В любом случае то, что результат будет большим у вышестоящих сомнений нет.

Большое спасибо за ответы
...все это временно... (с) Айэм
Re: Постраничный вывод в ADO. Что это и как с ним работать?
От: KGP http://kornilow.newmail.ru
Дата: 20.02.04 08:19
Оценка:
Здравствуйте, mihauzen, Вы писали:

Сортировка результата какая ?
... << RSDN@Home 1.1.0 stable >>
Re[2]: Постраничный вывод в ADO. Что это и как с ним работат
От: mihauzen Украина  
Дата: 20.02.04 15:23
Оценка:
Здравствуйте, KGP, Вы писали:

KGP>Здравствуйте, mihauzen, Вы писали:


KGP>Сортировка результата какая ?


Сортировка должна производиться по какому-нибудь одному столбцу в прямом или обратном порядке. А причем тут сортировка и как это может помочь?
...все это временно... (с) Айэм
Re: Постраничный вывод в ADO. Что это и как с ним работать?
От: oRover Украина  
Дата: 21.02.04 11:12
Оценка:
Здравствуйте, mihauzen, Вы писали:

Re: vbs+access
Автор: oRover
Дата: 16.08.03
... << RSDN@Home 1.1.0 stable >>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.