Delphi-Help

  • Increase font size
  • Default font size
  • Decrease font size
Главная Статьи FireBird/Interbase Режим работы TpFIBDataSet "Ограниченный локальный буфер"

Режим работы TpFIBDataSet "Ограниченный локальный буфер"

Оцените материал
(1 Голосовать)

Режим работы TpFIBDataSet "Ограниченный локальный буфер"

Режим работы впервые был предложен в компонентах gb_Datasets от Сергея Спирина. Теперь аналогичная функциональность реализована непосредственно в коде FIBPlus. Особенность данного режима состоит в том, что при навигации по TpFIBDataSet не будет происходить полное скачивание всех записей, которые возвращаются запросом. Фактически, реализуется имитация непосредственного доступа к произвольным записям за счет выполнения дополнительных запросов. Технология накладывает ряд требований на запрос. В частности, необходимым требованием является использование ORDER BY в SelectSQL. Причем, комбинация значений полей, входящих в выражение ORDER BY, должна быть уникальной. Во-вторых, для реального быстродействия желательно иметь два индекса - по возрастанию и по убыванию - для данной комбинации полей.

Технологию можно пояснить следующим простым примером. Имея запрос в SelectSQL:

·         SELECT * FROM TABLE
·         ORDER BY FIELD

мы можем получить несколько первых записей, делая последовательный fetch. Если мы хотим сразу посмотреть последние записи, то вместо полного выкачивания на клиента всех записей данного запроса, можно выполнить дополнительный запрос с обратной сортировкой:

·         SELECT * FROM TABLE
·         ORDER BY FIELD DESC

Очевидно, что последовательный fetch нескольких записей вернет нам последние записи относительно первоначального запроса. Аналогичные запросы выполняются для точного позиционирования на произвольную запись, а также на записи выше и ниже текущей:

·         SELECT * FROM TABLE
·         WHERE (FIELD = x)

 

·         SELECT * FROM TABLE
·         WHERE (FIELD < x)
·         ORDER BY FIELD DESC

 

·         SELECT * FROM TABLE
·         WHERE (FIELD > x)
·         ORDER BY FIELD

 

Для реализации этой технологии в TpFIBDataSet добавлено новое свойство:

·         property CacheModelOptions:TCacheModelOptions, где
·          
·         TCacheModelOptions = class(TPersistent)
·         property BufferChunks: Integer ;
·         property CacheModelKind: TCacheModelKind ;
·         property PlanForDescSQLs: string ;
·         end;

BufferChunks в данном случае заменяет существующее свойство BufferChunks у TpFIBDataSet. Тип TCacheModelKind может принимать значения cmkStandard, для использования стандартной работы локального буфера, и cmkLimitedBufferSize, для использования новой технологии ограниченного локального буфера. Размер буфера - это количество записей, указанных в свойстве BufferChunks.

Свойство PlanForDescSQLs позволяет указать отдельный план для запросов с обратной сортировкой.

Необходимо отметить, что при использовании технологии ограниченного локального буфера:

·         нельзя включать режим CachedUpdate;
·         свойство RecNo будет возвращать неправильные значения;
·         локальная фильтрация не поддерживается;
·         работа с BLOB-полями в текущей версии не гарантируется;
·         в PrepareOptions необходимо включать опцию psGetOrderInfo.

Кэширование BLOB-полей на клиенте

Поддержка BLOB-полей на уровне InterBase и Firebird API во многом определила возникновение и реализацию данной идеи. При выполнении любого запроса SELECT с участием BLOB-полей, клиентское приложение на самом деле получает на реальные значения этих полей, а лишь BLOB_ID. В дальнейшем, если приложение явным образом пытается прочитать значение конкретного BLOB-поля, сервер возвращает значение по BLOB_ID. То есть, фактически, обработка BLOB-полей уже отделена от работы с полями других типов. Делается это, поскольку в большинстве случаев, размеры BLOB-полей достаточно велики, и без особой нужды пересылать такие объемы по сети не имеет смысла.

Дальнейшее развитие этого механизма позволяет вообще избавиться от пересылки BLOB-полей, которые уже были получены приложением в предыдущих сеансах работы с сервером и с тех пор не изменялись. Основной реализации служит тот факт, что при изменении значения BLOB-поля меняется также и его BLOB_ID. Следовательно, приложению достаточно просто сравнить «старый» и «новый» BLOB_ID, чтобы определить необходимость получения BLOB-поля из базы данных. Полученные BLOB-поля сохраняются на локальном диске в указанном каталоге и при необходимости берутся оттуда, а не закачиваются с сервера.

В TpFIBDatabase добавлено новое свойство BlobSwapSupport: TBlobSwapSupport; где

TBlobSwapSupport = class(TPersistent)
property Active: boolean default False;
property SwapDir: string;
property MinBlobSizeToSwap: integer default 0;
end;

При включении BlobSwapSupport.Active := True, FIBPlus автоматически будет сохранять полученные BLOB-поля в указанном каталоге (свойство SwapDir). По умолчанию свойство SwapDir принимает значение равное {APP_PATH}, то есть, равное каталогу, в котором находится исполняемое приложение. При необходимости, можно указать также подкаталог, в котором будут сохраняться BLOB-поля. Например, SwapDir := '{APP_PATH}' + '\BLOB_FILES\'

Помимо нового свойства в TpFIBDatabase было добавлено 4 новых события:

property BeforeSaveBlobToSwap: TBeforeSaveBlobToSwap;
property AfterSaveBlobToSwap: TAfterSaveLoadBlobSwap;
property AfterLoadBlobFromSwap: TAfterSaveLoadBlobSwap;
property BeforeLoadBlobFromSwap: TBeforeLoadBlobFromSwap;

где

  • TBeforeSaveBlobToSwap = procedure(const TableName, FieldName: string; RecordKeyValues: array of variant; Stream: TStream; var FileName: string; var CanSave: boolean) of object;
  • TAfterSaveLoadBlobSwap = procedure(const TableName, FieldName: string; RecordKeyValues: array of variant; const FileName: string) of object;
  • TBeforeLoadBlobFromSwap = procedure(const TableName, FieldName: string; RecordKeyValues: array of variant; var FileName: string; var CanLoad: boolean) of object;

Обработчики служат для более гибкого управления процессом сохранения и чтения BLOB-полей с диска. В частности, в обработчиках перед сохранением BLOB-поля можно запретить сохранение конкретного BLOB-поля в зависимости от имени таблицы и поля, значений других полей записи, свободного места на диске и т.д. Регулировать процесс сохранения можно и при помощи свойства MinBlobSizeToSwap, в котором можно задать минимальный размер BLOB-полей, которые будут сохраняться на диске.

Технология имеет ряд ограничений:

Таблица должна иметь первичный ключ.

Чтение BLOB-полей должна производиться компонентом TpFIBDataSet.

Приложение само должно следить за свободным местом на диске. В частности, такую функцию можно реализовать в обработчике события BeforeSaveBlobToSwap.

К сожалению, после backup/restore базы данных внутри базы данных происходит замена всех BLOB_ID, а потому локальный кэш теряет актуальность и автоматически вычищается. При очередном подключении к базе данных запускается специальный трэд, который в отдельном подключении проверяет весь кэш на диске на наличие соответствующих BLOB-полей в базе данных. Для отсутствующих BLOB-полей файлы сразу же удаляются.

Прочитано 10152 раз

Авторизация



Счетчики