Delphi.FireDAC. Получение рядов (Fetching)

Эта статья посвящена так называемому “Fetchig”. Дословно это “Получение рядов”. Она основана на официальной документации

-старая версия

-новая версия

Когда SQL команда выполнена и вернула некоторое множество данных, DBMS создает курсор на сервере. Приложение использует курсор, чтобы получать ряды из базы. В зависимости от DBMS может быть несколько типов курсоров. Чтобы выбрать тип курсора, достаточно выбрать свойство FetchOptions.CursorKind. По умолчанию, FireDAC выберет наиболее быстрый курсор (ckAutomatic).

Курсоры DBMS чувствительны к контексту транзакции, где они были открыты. Подробнее в главе “Managing Transactions”

Получение рядов (Rowset Fetching)

Получение рядов позволяет выбрать число записей, которые будут получены с сервера за один “сетевой проход”. Это можно настроить отдельно для каждого исполняемого SELECT, минимизируя таким образом число “сетевых проходов”, указывая это в свойстве RowsetSize

Размер множества управляется свойством FetchOptions.RowsetSize. Чем выше это значение, тем быстрее FireDAC получит результаты множества, но задержка при получении следующей порции возрастает также. Ставя большие значения, производительность начинает падать. На практике высокое значение это 2000-3000.

Учтите, что не все DBMS поддерживают получение рядов. Однако, FireDAC эмулирует получение за счет скорости. Эмулированный “фетчинг” это снижение скорости на 50%.

FireDAC получает ряды согласно свойству FetchOptions.Mode
  • fmOnDemand— ряды автоматически получаются, когда множество пытается сдвинуть текущую позицию за “последнюю полученную позицию из прошлой порции”
  • fmAll— все ряда автоматически получаются сразу же после получения SQL команды. Это сходно вызову метода FetchAll
  • fmManual–программист получает ряды в ручную
  • fmExactRecsMax–получается число рядов равное RecsMax, если оно отличается (например в конце множества, в последней порции), то вызывается исключение.

FireDAC is fetching rowsets according to the FetchOptions.Mode property:

Если в True стоит свойство FetchOptions.Unidirectional, то перед получением следующего “rowset”, предыдущее удаляется из памяти. Это позволяет сохранять память компьютера при больших множествах.

Когда все записи получены, то свойство TFDDataSet.SourceEOF устанавливается в True.


“Паджинация” по рядам (Rows Paging)

FetchOptions.RecsSkip и RecsMax позволяют перемещаться по страницам через все множество. Страница, это грубо говоря – набор из нескольких записей.  После того как курсор открыт, первые RecsSkip “покидаются”. Иными словами, они уже открыты и их не надо “фетчить”, получать. Остальные записи до RecsMAx будут “профетчены”. Изменения свойств RecsSkip and RecsMax не сработают, когда SQL инструкция в состоянии Prepared. Таким образом, до того как получить следующую страницу, инструкция должна быть приведена в состояние Unprepared. Далее в документации приводится такой пример:


Отложенный “фетчинг”. (Delayed Fetching)

Множество может включать BLOB поля или другие вложенные колонки. В общем случает, такие колонки замедляют получение множества. FireDAC позволяет отложить получение таких колонок, пока их значения на самом деле не понадобятся. Чтобы сделать так, нужно настроить свойство FetchOptions.Items

-Когда fiBlobs выключено, FireDAC откладывает получение BLOB полей. Метод FetchBlobs получает BLOB значения для текущего множества. Альтернативно, первое чтение BLOB значения автоматически вызывает FetchBlobs, когда Mode <> fmManual

-Когда fiDetails выключено, FireDAC откладывает вложенные множества. Метод FetchDetails получает вложенные множества. Также fiDetails контролирует master-details handling

Для отложенного “фетчинга” прочтите раздел Update Command Generation.

Исключение fiBlobs и fiDetails из FetchOptions не изменяет команды SELECT. Если DBMS передает BLOB значения по значению (e.g., Oracle LONG, MySQL, SQL Server, SQLite), то BLOB значения будут доставлены клиенту через сеть. Однако, они не будут сохранены в клиентском кэше множества. А если DBMS передает значения BLOB по ссылке (e.g., Oracle CLOB / BLOB, Interbase, Firebird), то BLOB значения не будут доставлены и сохранены.


“Рефетчинг” (Refetching Rows)

Иногда приложению нужно добавить новое множество к старому или просто обновить ряды, для этого существует методы FetchAgain и Refresh

Далее в документации приводится таблица рекомендуемых параметров на разные случаи жизни

15

by Stanislav_Panteleev