слушайте Wamr'a, Wamr плохого не посоветует
достаточно посмотреть на то, что попадает в профайлер в каждом проходе в первом цикле и что во втором
а) Connection, Statement
аксапта "честно" отправляет запрос "select top 1000 from myTable"
-exec sp_cursoropen ...
открывает курсор и фетчит записи ПО ОДНОЙ
-exec sp_cursorfetch 180150058, 2, 1,
1 - по одному вызову на запись
обратите внимание на последний параметр (1) и
вот это
б) WHILE SELECT и табличная переменная
-exec sp_cursorexecute - у нас есть уже есть "откомпилированный" MSSQL запрос, так что мы его используем повторно. MSSQL не парсит его повторно, не строит план исполнения (он уже есть), это хорошо, что-то мы на этом сэкономили.
но все это фигня

-exec sp_cursorfetch 180150050, 2, 1,
16 - по одному вызову на несколько записей
обратите внимание на последний параметр, он равен 16 (у меня так с последней версией MDAC, сколько будет у вас - не знаю)
т.е. мы получаем recordset кусками по 16 записей
в конечном счете мы немного выиграли на суммарном траффике
но и это тоже фигня
мы сделали В РАЗЫ меньше fetch() по сравнению с первым вариантом
ну а раз время выполнение SELECT * FROM MYTABLE у нас мало по сравнению со временем на то, чтобы отослать результаты клиенту (запрос тривиальный), выигрыш у нас идет в разы, если не на порядок
а кэширование тут не при чем, SELECT * FROM MYTABLE, даже с условием WHERE, но не по уникальному ключу у нас не кэшируются, разве что с CacheLookup=EntireTable, но этот случай мы рассматривать не будем..
З.Ы. вот уж дорвался до форума так дорвался

З.З.Ы. до QueryRun не добрался, как-нибудь потом
подумалось.. насчет зависимости числа fetch-ащихся записей от версии MDAC я похоже того.. немного погорячился

для одинаковых версий аксапты оно скорее всего будет одинаковым