Re[4]: Загрузка большого объема данных
От: bmv Удмуртия  
Дата: 25.06.03 05:05
Оценка:
Здравствуйте, LG, Вы писали:

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


LG>>>3. "как-то реагировать на прокрутку" (не знаю, где прокрутка, на вскидку) TClientDataSet.DisableControls/TClientDataSet.EnableControls

bmv>>Имею ввиду что если искусственно закачивать данные порциями (экранами), то возникает проблема с полосой прокрутки...
bmv>>Вот если бы что-то по типу как это делает сам MSSQL Enterprise Manager, когда открывает большие таблицы...
LG>

LG>Вопрос порционной(постраничной) выборки тесно связан с вопросом нумерации строк в запросе (см. FAQ.Нумерация записей в запросе). Другими словами, для того, чтобы выбрать N-ую порцию из результатов запроса, нужно сначала пронумеровать результаты этого запроса.
LG>Отсюда и похожие методы решения
LG>Вариант 1 «Классический».

LG>SELECT TOP 100 * FROM MyTable

LG>WHERE id NOT IN (SELECT TOP 100 id FROM MyTable ORDER BY id) ORDER BY id




LG>Главный недостаток этого метода в в том, что т.к. TOP n записей выбираются уже из конечного результата запроса, то проверка условия WHERE будет выполняться для каждой строки главного запроса. При этом, время выполнения этой проверки будет расти вместе с номером выбираемой порции(страницы). Если, например, таблица содержит 100 записей и необходимо выбирать данные порциями по 10 записей, то
LG>для 2-ой порции нужно будет будет проверять подзапрос из 10 записей
LG>для 3-ей порции нужно будет будет проверять подзапрос из 20 записей
LG>для 4-ой порции нужно будет будет проверять подзапрос из 30 записей и т.д.
LG>Достоинство метода в его универсальности, академичности. Он не требует специфики T-SQL, этот метод можно применить практически на любом SQL-сервере.
LG>Вариант 2 «Эффективный, специфический для T-SQL».
LG>Как и в случае нумерации строк данный метод основан на использовании временной таблицы. Для удобства оформим наш запрос как хранимую процедуру, возвращающую n-ую порцию(страницу), содержащую m записей

LG>CREATE PROCEDURE dbo.get_this_page (@rec_per_page int, @page_num int) AS

LG>SELECT identity(int, 1,1) AS RowNum, MyId AS OrigId INTO #tmp FROM mytable

LG>SELECT b.* FROM #tmp AS a

LG>INNER JOIN mytable AS b on a.OrigId = b.MyId

LG>WHERE a.RowNum BETWEEN (@rec_per_page * @page_num + 1)

LG>AND (@rec_per_page * (@page_num + 1))

LG>DROP TABLE #tmp




LG>Прмечания.
LG>- предложенный вариант процедуры будет блокировать базу tempdb на все время выполнения 1-го запроса. Если время блокировки становиться неприемлимым, то необходимо разбить этот запрос таким образом

LG>CREATE TABLE #temp(RowNum int identity, OrigId int)

LG>INSERT INTO #temp(OrigId) SELECT MyId FROM mytable




LG>- Если, поле MyId было создано признаком «IDENTITY», то это поле в запросе необходимо «завернуть» в функцию «CONVERT», иначе будет сообщение об ошибке.
LG>Glory

Спасибо за развернутый ответ, все это, конечно, здорово, только все-таки как решить при этом вопрос с прокруткой данных пользователем
Michael
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.