Работа платформы Terrasoft с памятью.

Добрый день.
Подскажите пожалуйтся, что можно почитать по поводу работы платформы Terrasoft с памятью?

Я сейчас занимаюсь реализацией механизма обмена данными и при текущих объемах этих самых данных Terrasoft жутко течет.

Нравится

12 комментариев

Добрый день.

К сожалению какого-то конкретного материала по работе платформы с памятью не существует. Вопрос слишком абстрактный. Не могли бы Вы уточнить более конкретно, что Вас интересует?

Меня интересует, как заставить платформу более экономно расходовать память при подобных операциях.
У меня есть таблица, хранящая соответствие контрагентов и контактов в отношении многие-ко-многим. Мне нужно перенести ее содержимое в Terrasoft из внешней программы посредством COM. SQL-запросом я подготавливаю списки идентификаторов контрагентов и контактов и по одному записываю их в эту таблицу соответствий. При 5000 таких записей, Terrasoft забирает положенные ему 2 Гб памяти на 32-битной системе и падает с OutOfMemory.
Но когда я подобным образом дергаю контрагентов в источнике и записываю по одному в Terrasoft-приемник потребление памяти более-менее приемлимое (500-600 МБ).
Вот мне и интересно, как корректнее с точки зрения потребления памяти производить массовое чтение-запись из/в Terrasoft?
Вариант с проведением подобных операций средствами сервера БД не подходит.

Петр, скорее всего Вы делаете что-то неправильно, но судя из описания трудно понять что именно.

5000 записей (зависит конечно от структуры) очень малое количество, чтобы забирать 2 Гб.

Возможно Вы не закрываете датасет после выборки данных или берете всегда GetNewItemByUSI на каждую запись. Пришлите, пожалуйста, пример кода как и что Вы делаете для анализа.

"Ерошенко Петр Семенович" написал:Мне нужно перенести ее содержимое в Terrasoft из внешней программы посредством COM
...
Вариант с проведением подобных операций средствами сервера БД не подходит.

Петр, почему не подходит? В mssql есть поддержка COM. Что это за внешняя программа?

"Осауленко Александр" написал:Петр, почему не подходит? В mssql есть поддержка COM. Что это за внешняя программа?

Ну, во-первых Terrasoft не везде на MS SQL. Во-вторых, попадаются достаточно сложные условия на установку соответствия между сущностью в источнике и сущностью в приемнике. Например, контрагента сначала нужно искать по сочетанию ИНН/КПП. Если нашлась только одна запись, то все отлично. Если нет - то поиск продолжается только по ИНН, причем могут попадаться оригинальные ИНН типа "1", "11111111" и т. п. Оно на T-SQL, в принципе, реализуемо, но провожусь я с этим гораздо дольше, чем с кодом в TS. В самом крайнем случае из TS я могу показать список вариантов, в котором пользователь может выбрать нужный. И в-третьих, самое противное, наличие программной логики в обработчиках событий AfterAppend, AfterPost, AfterDelete, AfterEdit. Продублировать ее в SQL?

Петр, т.е. у вас уже написана довольно сложная логика в конфигурации и просто не хотите ее дублировать на уровне СУБД?

Попробуйте таким способом.

Если есть возможность, в таблицу-источник данных добавьте поле IsProcessed. Перед обработкой, для всех записей сбросьте это поле в 0. При обращение к таблице-источнику пишите условие

Select top 1000  ... From ... Where IsProcessed <> 1 and ...

После перекачки каждой записи надо будет IsProcessed перевести в 1.
Т.е. вы в бесконечном цикле while открываете свой датасет пока RecordCount > 0.
Какие плюсы : каждый раз после закрытия датасета очищается память (точнее спустя какое-то время пока сборщик мусора ее не освободит), следовательно можно избежать OutOfMemory.
Минусы: Чуть дольше будет идти импорт за счет обновления поля IsProcessed.

Я примерно так и поступаю, только у меня есть таблица, в которой хранятся ID объектов в источнике и приемнике. После завершения импорта очередного объекта создается запись в этой таблице. Плюсов больше: не нужно модифицировать таблицу-источник (их может быть много) и поиск объекта в приемнике нужно выполнять один раз. Таким образом, мне нужно импортировать только те объекты, которых нет в таблице соответствий.
Другой вопрос: как это пооптимальнее применять. Сейчас у меня есть глобальная переменная в скрипте, в которой храниться объект SelectQuery. Я в нем меняю значение параметра, получаю Dataset методом Open() и читаю значение. Может течь в этом месте, потому как этот код дергается очень часто?

Похоже что Вы делаете универсальный механизм, это не разовая и не периодическая загрузка из определенной БД.
Ту нужно искать универсальное решение.

 Сейчас у меня есть глобальная переменная в скрипте, в которой храниться объект SelectQuery. Я в нем меняю значение параметра, получаю Dataset методом Open() и читаю значение.

Петр, закрывате ли Вы потом Dataset?

Dataset.Close();

Также вместо Services.GetNewItemByUSI('');

попробуйте Services.GetSingleItemByUSI('');

"Олейник Дмитрий" написал:Петр, закрывате ли Вы потом Dataset?

Нет, попробую закрывать.

"Олейник Дмитрий" написал:Также вместо Services.GetNewItemByUSI('');

попробуйте Services.GetSingleItemByUSI('');


В принципе, я объект запроса получаю один раз и храню в глобальной переменной скрипта. Вы полагаете, что будет разница от того, как я его получаю, через GetNewItemByUSI или GetSingleItemByUSI?

Петр, в таком случае нет - разницы не будет. Конечно в том случае если и объект Dataset'а Вы также получаете один раз.
Попробуйте закрывать Dataset'ы. Если не поможет - тут не обойдемся без полного исходного кода, для его анализа.

Показать все комментарии