Имеется таблица в SQL сервере, в которой тьма тьмущая записей (несколько миллионов). Надо их прочитать и максимально быстро отдать.
Подскажите, кто знает, можно ли попросить OLE DB отдавать записи по мере их поступления с сервера? И как это сделать?
Вроде бы при открытии роусета можно установить бит DBPROPVAL_ASYNCH_INITIALIZE в DBPROP_ROWSET_ASYNCH, и потом получить указатели на IConnectionPointContainer и IDBAsynchStatus, и через всю эту канитель оповещаться о поступлении данных. Во всяком случае, такое впечатдение возникло при чтении SDK, главы 17 "Introduction to OLE DB".
Но вот беда — документация SDK по OLE DB не отличается особой ясностью, а сделать надо срочняк, прямо скажу — горит!
Если кто делал, поскажите!
Здравствуйте, bezlepkin, Вы писали:
B>Имеется таблица в SQL сервере, в которой тьма тьмущая записей (несколько миллионов). Надо их прочитать и максимально быстро отдать.
B>Подскажите, кто знает, можно ли попросить OLE DB отдавать записи по мере их поступления с сервера? И как это сделать?
Лучше соорудить собственное асинхронное чтение, не полагаясь на средатва провайдера. Например, если мне не изменяет память, MSSQL мучает связанный провайдер (linked server) так:
Один поток получает дескипторы рядов (HROW) через IRowset::GetNextRow
Другой поток по этим дескрипторам тащит из провайдера данные через IRowset::GetData
... Но реально толку от такого подхода может и не быть — Ибо вызов одного может блокировать вызов другого
Так что заводи два потока — фоновый будет читать HROW и данные, а основной будет эти данные возвращать клиенту.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Можно сконфигурировать SQL Server чтобы он отдавал данные асинхронно, т.е. не дожидаясь окончания считывания данных в свои буфера.
sp_configure 'show advanced options', 1
reconfigure with override
go
sp_configure 'cursor threshold', 100
reconfigure with override
go
sp_configure 'show advanced options', 0
reconfigure with override
go
Здравствуйте, bezlepkin, Вы писали:
B>Имеется таблица в SQL сервере, в которой тьма тьмущая записей (несколько миллионов). Надо их прочитать и максимально быстро отдать.
Давай разберемся
Куда отдаеш (Пользователю на экран?) и что с ними делаеш?
Обычно на экран отдается первая порция — а там постепенно подкачивается остальное (Такое делал
здесь и ненадо никаких супер наворотов) — но милион записей — это слишком.
Здравствуйте, Kostik00.
K>Давай разберемся
Доктору, исцелился сам
K>Куда отдаеш (Пользователю на экран?) и что с ними делаеш?
Отдаю данные в программу с весёлым названием ГОПА — графическая оболочка просмотра архивов (это не шутка, так в ТЗ!) SCADA-системы.
K>Обычно на экран отдается первая порция — а там постепенно подкачивается остальное (Такое делал здесь и ненадо никаких супер наворотов) — но милион записей — это слишком.
Для SCADA-систем миллион записей — это только закусить перед завтраком. Цикл опроса может быть (например) 1 мс, то есть с одного датчика получаем 1000 значений в сек, а всего этих приборов — легко может быть и сотня, и много больше.
Ну, это к слову. Непосредственно же решение оказалось простым, как грабли. И очень похоже на то, что предлагал Коваленко Дмитрий (см. выше в этой ветке). Данные получаются порциями по N строк. Полученная порция ставится в очередь на "отдачу", а другой поток эту очередь разгружает. И всё это в цикле, пока все данные не приплывут с сервера.
Собственно получение порций данных реализовано так:
1) IRowset::GetNextRows()
2) IRowset::GetData()
3) IRowset::ReleaseRows()
Самое весёлое, что никакие средства асинхронной обработки OLE DB не потребовались.