Сохранение в поток (постановка)

Материал из GedeminWiki
Перейти к: навигация, поиск

Требования к новому алгоритму сохранения в поток были первоначально сформированы в результате дискуссии на сайте gsbelarus.com:

  1. Увеличение скорости минимум в 10 раз;
  2. Уменьшение размера файла минимум в 10 раз (при использовании двоичного формата);
  3. Возможность сохранения в формате XML;
  4. Предусмотреть возможность сохранения только объектов измененных после указанной даты;
  5. Предусмотреть возможность инкрементного сохранения объектов;
  6. Предусмотреть возможность расширенного и краткого отображения информации о ходе процесса. Дать пользователю возможность прервать процесс в любой момент времени;
  7. Предусмотреть возможность запуска процесса из командной строки;
  8. Предусмотреть возможность сохранения всей базы данных в потоке;
  9. Процедура должна обрабатывать миллион записей на компьютере с 512 Мб оперативной памяти за приемлемое время;
  10. Формирование потока данных и загрузка его на базу должна осуществляться не в монопольном режиме.
См. сравнение механизмов репликации и сохранения данных в поток в статье Сохранение в поток и репликация.

Содержание

Сценарии использования сохранения в поток

Сценарий Чего хотим добиться
Пользователь выбирает объект или группу объектов и сохраняет их в поток. Минимум десятикратного ускорения по сравнению с действующим алгоритмом. Меньшего размера файла. Контроля над ходом процесса. Возможности прервать процесс в любой момент времени.
Пользователь указывает сохранить в поток объекты, измененные после указанной даты. Аналогично предыдущему. Система производит в базе данных поиск всех объектов, измененных после указанной даты (как быть со множествами?).
Разработчик сохраняет настройку в формате XML. Текстовый файл, содержащий настройку ввиде форматированного XML, можно сравнить с прежней версией настройки и таким образом определить что было изменено. Такие настройки можно помещать в хранилище StarTeam и использовать систему контроля версий.
Пользователь производит загрузку потока на базу данных. Ускорения процесса. Контроля над ходом выполнения и возможности прервать процесс в любой момент времени. Внятного разрешения конфликтных ситуаций: Обновлять записи всегда, Обновлять записи только если они новее, чем те, что находятся в базе данных, Пропускать записи. Возможности выставить действие по-умолчанию как для всего процесса, так и для объектов конкретного типа. Возможности сравнивать данные объектов при возникновении конфликта перезаписи уже существующего объекта. Возможности слияния данных двух объектов (подобно той, которая существует в механизме объединения двух записей).
Пользователь имеет головную базу и несколько перефирийных, на которых происходит редактирование данных. Периодически данные с перефирийных баз передаются на головную для консолидации, причем изменения от головной базы данных не передаются на перефирийные и изменения от одной перефирийной базы данных не передаются на другую. Возможности инкрементной передачи данных. Т.е. перадаваться должны только объекты измененные (добавленные) с момента последней передачи. Возможности передавать информацию об удаленных записях.
Пользователь имеет несколько баз между которыми необходим полный обмен информацией (репликация). Замены внешней утилиты репликации. Передачи только инкремента данных. Разрешения конфликтов в автоматическом и/или ручном режиме.

Увеличение скорости

Беглый анализ показывает, что основной проблемой существующего сохранения является использование рекурсии и бизнес объектов. Сейчас работает так:

  1. начинаем сохранять запись определенного типа (запись бизнес-объекта);
  2. создаем клиент датасет и переносим в него данные полей сохраняемой записи;
  3. записываем в поток служебную информацию и данные клиент датасета;
  4. находим поля-ссылки, создаем экземпляры бизнес-объектов соответствующего типа и рекурсивно вызываем процедуру сохранения в поток, т.е. переходим к п. 1.

Таким образом, в процессе сохранения объект одного и того же типа может создаваться неограниченное число раз.

Почему использование бизнес-объекта замедляет процесс?

  • Бизнес-объект является наследником от класса TIBDataSet и уже в силу этого он медленее при обращении к данным чем легковесный TIBSQL;
  • Формирование, последующий парсинг и переформирование запроса бизнес-объекта занимают значительное время;
  • При создании экземпляра бизнес-объекта в скрипт-контрол загружаются скрипт-функции перекрытых методов;

Использование пула объектов сведет к минимуму затраты по первым двум пунктам, но проблема отключения макросов для конкретного объекта остается не решенной.

Уменьшение размера файла

Уменьшения размера файла мы добьемся за счет отказа от рекурсии при формировании потока данных из-за которой мы имеем следующую внутреннюю структуру файла:

Save stream 1.png

Служебная информация и заголовок датасета записываются практически перед каждой записью, что существенно раздувает файл. В новом формате, записи одного типа будут сгруппированы:

Save stream 2.png

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

Нам понадобятся следующие структуры данных:

  • Список (пул) бизнес-объектов - BO
  • Список клиент-датасетов, где будет храниться информация бизнес-объектов - CL
  • Список идентификаторов записей, помещенных в поток - L

Списки BO и CL содержат всегда одинаковой количество элементов. Бизнес объекту с номером N из списка BO соответсвует клиент-датасет с таким же номером из списка CL.

Концептуально, алгоритм сохранения в поток выглядит следующим образом:

  1. Вызывается метод SaveToStream2, куда передается: 1) поток, куда будут записаны данные; 2) список закладок (выделенные записи); 3) детальный датасет (если есть); 4) флаг сохранять все записи или только текущую.
  2. В зависимости от настроек внутри метода организуется цикл по записям (выделенным или всем) или обрабатывается только текущая запись.
  3. Для каждой записи вызывается метод _SaveToStream2, куда передается
Персональные инструменты
Пространства имён

Варианты
Действия
Навигация
Инструменты