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

Материал из GedeminWiki
(Различия между версиями)
Перейти к: навигация, поиск
(Переработанный алгоритм сохранения в поток)
(Переработанный алгоритм сохранения в поток)
Строка 70: Строка 70:
 
Нам понадобятся следующие структуры данных:
 
Нам понадобятся следующие структуры данных:
  
* Список (пул) бизнес-объектов - BO
+
; BO : Список (пул) бизнес-объектов;
* Список клиент-датасетов, где будет храниться информация бизнес-объектов - CL
+
; CL : Список клиент-датасетов, где будет храниться информация бизнес-объектов;
* Список идентификаторов записей, помещенных в поток - L
+
; L  : Список идентификаторов записей, помещенных в поток.
  
 
Списки BO и CL содержат всегда одинаковой количество элементов. Бизнес объекту с номером N из списка BO соответствует клиент-датасет с таким же номером из списка CL.
 
Списки BO и CL содержат всегда одинаковой количество элементов. Бизнес объекту с номером N из списка BO соответствует клиент-датасет с таким же номером из списка CL.
Строка 78: Строка 78:
 
Концептуально, алгоритм сохранения в поток выглядит следующим образом:
 
Концептуально, алгоритм сохранения в поток выглядит следующим образом:
  
# Вызывается метод SaveToStream2, куда передается: 1) поток для записи данных; 2) список закладок, если надо сохранить выделенные выделенные пользователем записи. Список можно не указывать, тогда то, какие записи будут сохранены определяется четвертым параметром; 3) детальный датасет (если есть). Изначально этот механизм предназначался для копирования таких сущностей, как накладная, где мы должны скопировать шапку (мастер) и позиции (детальный датасет). Но для любой сущности могут появиться дополнительные информационные таблицы, т.е. таблицы связанные 1-1, которые также необходимо скопировать. Мы решали эту проблему в коде дублирования записи; 4) флаг сохранять все записи или только текущую.
+
# Вызывается метод SaveToStream2, куда передается:  
 +
## поток для записи данных;  
 +
## список закладок, если надо сохранить выделенные выделенные пользователем записи. Список можно не указывать, тогда то, какие записи будут сохранены определяется четвертым параметром;  
 +
## детальный датасет (если есть). Изначально этот механизм предназначался для копирования таких сущностей, как накладная, где мы должны скопировать шапку (мастер) и позиции (детальный датасет). Но для любой сущности могут появиться дополнительные информационные таблицы, т.е. таблицы связанные 1-1, которые также необходимо скопировать. Мы решали эту проблему в коде дублирования записи;  
 +
## флаг сохранять все записи или только текущую.
 
# В зависимости от настроек внутри метода организуется цикл по записям (выделенным или всем) или обрабатывается только текущая запись.  
 
# В зависимости от настроек внутри метода организуется цикл по записям (выделенным или всем) или обрабатывается только текущая запись.  
# Для каждой записи вызывается метод _SaveToStream2, куда передается: 1) 
+
# Для каждой записи вызывается метод _SaveToStream2, куда передается:  
  
  
 
[[Category:Постановка]]
 
[[Category:Постановка]]

Версия 01:42, 8 сентября 2007

Требования к новому алгоритму сохранения в поток были первоначально сформированы в результате дискуссии на сайте 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. детальный датасет (если есть). Изначально этот механизм предназначался для копирования таких сущностей, как накладная, где мы должны скопировать шапку (мастер) и позиции (детальный датасет). Но для любой сущности могут появиться дополнительные информационные таблицы, т.е. таблицы связанные 1-1, которые также необходимо скопировать. Мы решали эту проблему в коде дублирования записи;
    4. флаг сохранять все записи или только текущую.
  2. В зависимости от настроек внутри метода организуется цикл по записям (выделенным или всем) или обрабатывается только текущая запись.
  3. Для каждой записи вызывается метод _SaveToStream2, куда передается:
Персональные инструменты
Пространства имён

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