Re[5]: Работа с большими выборками в Windows-приложениях .NE
От:
Аноним
Дата:
16.08.03 10:05
Оценка:
Здравствуйте, Archistratig, Вы писали:
A>Сортирован — это слишком строгое требование. Вся эта схема работала бы, если бы в SQL существовала конструкция не TOP <n>, а нечто вроде FROM_ROW <m> TO_ROW <n>. Эмулировать ее пратически нереально кроме специальных случаев (вроде вставить результирующую выборку в темповую таблицу с identity и мделать еще один SELECT из нее и прочая неэффективная экзотика).
На самом деле такой подход показывает себя довольно эффективным.
Первые страницы открываются _намного_ быстрее, чем при использовании серверных курсоров, и смею уверить что большинству пользователей первой страницы будет достаточно.
В добавок, если используются в запросов сортировки то это зачастую приводит к неявному созданию временных таблиц.
A>А как насчет конкретных идей, как такое реализовать? Я тоже много фантазировал...
Re[5]: Работа с большими выборками в Windows-приложениях .NE
A>Сортирован — это слишком строгое требование. Вся эта схема работала бы, если бы в SQL существовала конструкция не TOP <n>, а нечто вроде FROM_ROW <m> TO_ROW <n>.
По-моему как раз твоя конструкция — слишком строгое требование. Её в MS SQL не вставишь. А сортировать по любому, хоть по первому полю всё-таки проще.
M>>Это уже дело клиентского приложения — собирать из кусочков.
A>Если б была такая конструкция — то без проблем...
Да нет, с сортировкой тоже без проблем.
Сначала вызываем посчитать count(*). Потом клиентское приложение посылает для первой порции запрос:
select top 100 a,b,c from tab1 order by a
Вкачивает результат в свой буфёр и показывает: всего столько-то записей, вот вам первые 100.
Если теперь пользователь хочет следующие — посылаем запрос:
select top 100 a,b,c from tab1 where a>='последнее предыдущее значение'order by a
Вкачиваем результат, добавляем во внутренний буфер. Естественно, отрабатываем строки-пересечения, то есть выкидываем дубли, возникшие от двух запросов.
Для перехода в конец — order by/desc использовать.
Естественно, нельзя перейти в произвольную часть — только PgUp/PgDown и Home/End.
... << RSDN@Home 1.1 beta 1 >>
Re[6]: Работа с большими выборками в Windows-приложениях .NE
Здравствуйте, mihailik, Вы писали:
M>Да нет, с сортировкой тоже без проблем.
M>Сначала вызываем посчитать count(*). Потом клиентское приложение посылает для первой порции запрос:
M>
M>select top 100 a,b,c from tab1 order by a
M>
M>Вкачивает результат в свой буфёр и показывает: всего столько-то записей, вот вам первые 100.
M>Если теперь пользователь хочет следующие — посылаем запрос: M>
M>select top 100 a,b,c from tab1 where a>='последнее предыдущее значение'order by a
M>
M>Вкачиваем результат, добавляем во внутренний буфер. Естественно, отрабатываем строки-пересечения, то есть выкидываем дубли, возникшие от двух запросов.
M>Для перехода в конец — order by/desc использовать.
M>Естественно, нельзя перейти в произвольную часть — только PgUp/PgDown и Home/End.
Блин, а если колнка a — строковая? Не годится такое рещение.
ЗЫ. Кстати, не совсем понятно, зачем с такой маниакальной настойчивостью жевать банальные вещи... ИМХО, с первого постинга на тему "select top 100" понятен предлагаемый алгоритм, видны все его достоинства и недостатки...
Re[7]: Работа с большими выборками в Windows-приложениях .NE
Здравствуйте, Archistratig, Вы писали:
A>ЗЫ. Кстати, не совсем понятно, зачем с такой маниакальной настойчивостью жевать банальные вещи... ИМХО, с первого постинга на тему "select top 100" понятен предлагаемый алгоритм, видны все его достоинства и недостатки...
Все таки последнее время алгоритмы для больших выборок пользуют несколько иные, по крайней мере на серверах приложений. При этом обычно в память выбирают все PK записей выборки, а при листании покадрово вытаскивают уже собственно саму выборку. Т.е. сначала делают такой запрос
select id from some_table where <condition>
Далее мы уже имеет как минимум COUNT, т.е. можем нормально позиционировать скроллер, при этом затраты памяти не сильно велики, count*4 при автоинкрементном pk, count*16 при guid pk. Далее при запросе записей с x по y выбирают собственно записи
select * from some_table where id in (список идентификаторов кадра, определенных по первой выборке в позициях между x и y)
Как правило выбирают не непосредственно с x по y, а некий фиксированногг размера кадр, чтобы уменьшить количество запросов к БД. Т.е. к примеру если кадр у тебя 4 тыс. записей, а на экран в грид влазит 20, то на каждые 200 страниц при листании грида будет только одна выборка.
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Archistratig, Вы писали:
AVK>select id from some_table where <condition>
AVK>Далее мы уже имеет как минимум COUNT, т.е. можем нормально позиционировать скроллер, при этом затраты памяти не сильно велики, count*4 при автоинкрементном pk, count*16 при guid pk. Далее при запросе записей с x по y выбирают собственно записи
AVK>select * from some_table where id in (список идентификаторов кадра, определенных по первой выборке в позициях между x и y)
Спасибо, классная идея... А запрос получается — динамический? Не очень радостно (люблю хранимые процедуры), но — приятно. Память конкретно экономится.
Re[9]: Работа с большими выборками в Windows-приложениях .NE
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Archistratig, Вы писали:
A>>Спасибо, классная идея... А запрос получается — динамический? Не очень радостно (люблю хранимые процедуры),
AVK>Можно хранимой процедурой, если заталкивать список id не в select а во временную табличку.
...либо воспользоваться массивом (тем, у когоа оракул), либо таблицей (у кого M$SQL)
Re[11]: Работа с большими выборками в Windows-приложениях .N
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Archistratig, Вы писали:
A>>ЗЫ. Кстати, не совсем понятно, зачем с такой маниакальной настойчивостью жевать банальные вещи... ИМХО, с первого постинга на тему "select top 100" понятен предлагаемый алгоритм, видны все его достоинства и недостатки...
AVK>Все таки последнее время алгоритмы для больших выборок пользуют несколько иные, по крайней мере на серверах приложений. При этом обычно в память выбирают все PK записей выборки, а при листании покадрово вытаскивают уже собственно саму выборку. Т.е. сначала делают такой запрос
AVK>select id from some_table where <condition>
AVK>Далее мы уже имеет как минимум COUNT, т.е. можем нормально позиционировать скроллер, при этом затраты памяти не сильно велики, count*4 при автоинкрементном pk, count*16 при guid pk. Далее при запросе записей с x по y выбирают собственно записи
AVK>select * from some_table where id in (список идентификаторов кадра, определенных по первой выборке в позициях между x и y)
AVK>Как правило выбирают не непосредственно с x по y, а некий фиксированногг размера кадр, чтобы уменьшить количество запросов к БД. Т.е. к примеру если кадр у тебя 4 тыс. записей, а на экран в грид влазит 20, то на каждые 200 страниц при листании грида будет только одна выборка.
... << RSDN@Home 1.1 beta 1 >>
Re[12]: Работа с большими выборками в Windows-приложениях .N
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Archistratig, Вы писали:
A>>...либо воспользоваться массивом (тем, у когоа оракул), либо таблицей (у кого M$SQL)
AVK>В общем да, в любом случае надо мерять что быстрее. В одном случае проигрываем на времени работы парсера, в другом на транзакции и БДшную специфику.
Я тут покопался и нашел, что для MS SQL быстрее всего работает вариант передачи набора id в виде строки XML с последующим парсингом через OpenXML и JOIN (вместо IN). Экономия происходит за счет того, что не нужно делать N вызовов INSERT для вставки данных в темповую таблицу.
Хотел проверить вариант с передачей параметров типа таблица в хранимую процедуру через ADO .NET, но не нашел пока, как это сделать...
Кто-нибудь знает, как организовать такое вуду?
Re[7]: Работа с большими выборками в Windows-приложениях .NE
Здравствуйте, Archistratig, Вы писали:
A>Я тут покопался и нашел, что для MS SQL быстрее всего работает вариант передачи набора id в виде строки XML с последующим парсингом через OpenXML и JOIN (вместо IN).
А с чем сравнивал? А тесты и результаты можно в студию?
A> Экономия происходит за счет того, что не нужно делать N вызовов INSERT для вставки данных в темповую таблицу.
А их не надо делать раздельно, надо формировать один запрос с кучей insert и отправлять его целиком.
Здравствуйте, Archistratig!
Давненько я тут не появлялся, но было время когда Вы писали:
A>Сортирован — это слишком строгое требование. Вся эта схема работала бы, если бы в SQL существовала конструкция не TOP <n>, а нечто вроде FROM_ROW <m> TO_ROW <n>. Эмулировать ее пратически нереально кроме специальных случаев (вроде вставить результирующую выборку в темповую таблицу с identity и мделать еще один SELECT из нее и прочая неэффективная экзотика).
Когда-то я тоже сталкивался с такой проблеммой. Добрые люди подсказали решение.
К примеру P — номер страницы
N — количество записей на странице
тогда получается следующая картина для 5 страницы из 20 записей
select * from
(select top 20 * from
(select top 100 * from tbl order by tbl_id) as tmp1
order by tmp1.tbl_id desc) as tmp2
order by tmp2.tbl_id
На выходе получится именно то, что вы и хотели <from 80 to 100>
Возможно этот метод вы отнесете к "неэффективной экзотике", но лично меня этот метод устраивает.
Если-же в нем есть каки-то недостатки — хотелось-бы о них услышать.
... << RSDN@Home 1.1 beta 2 >>
Re[6]: Работа с большими выборками в Windows-приложениях .NE
AW>Если-же в нем есть каки-то недостатки — хотелось-бы о них услышать.
посмотрел в соседнем форуме про БД, там говорят что при большом количестве записей будет тормозить
я у себя проверил, на 10000 работает отлично
(конечно нужно сделать индекс по сортируемой колонке)
спасибо за такой интересный способ постраничной выборки!
Re[6]: Работа с большими выборками в Windows-приложениях .NE
Здравствуйте, Alex Warm, Вы писали:
AW>Когда-то я тоже сталкивался с такой проблеммой. Добрые люди подсказали решение. AW>К примеру P — номер страницы AW>N — количество записей на странице AW>тогда получается следующая картина для 5 страницы из 20 записей AW>
AW>select * from
AW>(select top 20 * from
AW>(select top 100 * from tbl order by tbl_id) as tmp1
AW>order by tmp1.tbl_id desc) as tmp2
AW>order by tmp2.tbl_id
AW>
AW>На выходе получится именно то, что вы и хотели <from 80 to 100> AW>Возможно этот метод вы отнесете к "неэффективной экзотике", но лично меня этот метод устраивает. AW>Если-же в нем есть каки-то недостатки — хотелось-бы о них услышать.
Метод — супер. Спасибо. Оценил.
Re[3]: Работа с большими выборками в Windows-приложениях .NE
Здравствуйте, Archistratig, Вы писали: A>В том и проблема, что по требованиям закзачика так сделать нельзя. Выбрка должна возвращать все записи по условию, а не первые N.
Нет такого требования. Требования заказчика могут касаться только того, что видно на экране. Поскольку в задаче фигурирует пейджинг, то никто не сможет определить, были ли в действительности переданы все миллионы записей в приложение. Достаточно отдельно сделать запрос select count * from ..., чтобы написать полное количество записей.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: Работа с большими выборками в Windows-приложениях .NE
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Archistratig, Вы писали: A>>В том и проблема, что по требованиям закзачика так сделать нельзя. Выбрка должна возвращать все записи по условию, а не первые N. S>Нет такого требования. Требования заказчика могут касаться только того, что видно на экране. Поскольку в задаче фигурирует пейджинг, то никто не сможет определить, были ли в действительности переданы все миллионы записей в приложение. Достаточно отдельно сделать запрос select count * from ..., чтобы написать полное количество записей.
Так бывает когда заказчик сам давно когда-то программил, он то видел, он тут знает ... С такими труднее всего...