странное расходование памяти

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

странное расходование памяти

Сообщение nusya » 07.01.2009 23:13:40

добавляю из талицы .dbf чуть больше 400 тыс записей в таблицу mysql
по мере добавления ресурс памяти занимаемый программой project1 увеличивается и в конце добавления составляет до 1.5Гб
при добавлении использую методы SQLQuery1.Insert; SQLQuery1.ApplyUpdates;

после добавления набар данный SQLQuery1.Close я закрываю.
закрывается программа долго, порядка 3-4 мин, и при этом занимает почти 100% ресурсов проца.

что это, ошибка в lazarus или что иное?
nusya
новенький
 
Сообщения: 19
Зарегистрирован: 15.09.2008 12:58:15

Re: странное расходование памяти

Сообщение GrayEddy » 08.01.2009 02:35:41

Нет, это не ошибка, все правильно :)
1, 5 Гб - это и есть 400 000 записей в буфере, которые вы записываете в таблицу в БД одним махом.
Если вкратце - это 400 000 сформированных строк типа "INSERT INTO ..."
Решение: записываем поблочно по 1000 (примерно) записей. Вставить Application.ProcessMessages.Снова прочитали 1000 записей - записали. Application.ProcessMessages. И т д. Работает намного быстрее.
GrayEddy
постоялец
 
Сообщения: 375
Зарегистрирован: 06.05.2005 09:37:56

Re: странное расходование памяти

Сообщение nusya » 08.01.2009 12:20:18

Вот часть кода, где происходит добавление. Как видишь Application.ProcessMessages; присутсвтует при каждой итерации цикла. Но какое отношение Application.ProcessMessages имеет к БД и к освобождению ресурсов. После добавления набары данных я закрываю. При этом ресурсы не освобождаются. Ресурсы начинают освобождаться только при закрытии самой програмки.

Код: Выделить всё
while not Dbf1.EOF do begin
    SQLQuery1.Insert;
    SQLQuery1.FieldValues['xkey']:=Dbf1.FieldValues['xkey'];
    SQLQuery1.FieldValues['service']:=Dbf1.FieldValues['service'];
    SQLQuery1.FieldValues['tariff']:=Dbf1.FieldValues['tariff'];
    SQLQuery1.FieldValues['servcount']:=Dbf1.FieldValues['servcount'];
    SQLQuery1.FieldValues['servcount2']:=Dbf1.FieldValues['servcount2'];
    SQLQuery1.FieldValues['tabnumber']:=Dbf1.FieldValues['tabnumber'];
    SQLQuery1.FieldValues['spec']:=Dbf1.FieldValues['spec'];
    SQLQuery1.FieldValues['an_tariff']:=Dbf1.FieldValues['an_tariff'];
    SQLQuery1.FieldValues['mes']:=Dbf1.FieldValues['mes'];
    SQLQuery1.FieldValues['god']:=Dbf1.FieldValues['god'];
    SQLQuery1.FieldValues['n_pol']:=Dbf1.FieldValues['n_pol'];
    SQLQuery1.FieldValues['bukvi']:=Dbf1.FieldValues['bukvi'];
    SQLQuery1.ApplyUpdates;
    Dbf1.Next;
    ProgressBar1.Position:=i;
    Inc(i);
    Application.ProcessMessages;
  end;
  Dbf1.Close;
nusya
новенький
 
Сообщения: 19
Зарегистрирован: 15.09.2008 12:58:15

Re: странное расходование памяти

Сообщение MageSlayer » 08.01.2009 14:48:49

Вроде бы SQLQuery1.Post нужно делать после заполнения полей.

Application.ProcessMessages - вроде никакого отношения к БД не имеют.
MageSlayer
постоялец
 
Сообщения: 216
Зарегистрирован: 07.09.2006 12:30:44

Re: странное расходование памяти

Сообщение Vadim » 08.01.2009 16:26:21

Application.ProcessMessages - это чтобы программа не зависала на "тяжёлых" процессах и было видно, что она ещё работает, а не стоит колом...
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: странное расходование памяти

Сообщение alexs » 08.01.2009 18:20:47

Для массовых операций вставки - не нужно использовать буфер набора данных SQLQuery1. А оператор Insert именно это делает. Полсмотри у него методы Execute и у TSQLConnection - метод ExecuteDirect.
Я сам именно с этими наборами не работаю - но по логике вещей именно они должны обеспечитвать прямое выполнение SQL запроса - без использования буфера.

А в твоём примере - посел заполнения каждой итерации необходимо делать POST а ApplyApdates - либо после всего цикла, либо переодически - через 1000 - 2000 итераций.
Но - это не самый лучший метод.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: странное расходование памяти

Сообщение nusya » 08.01.2009 21:38:33

alexs писал(а):Для массовых операций вставки - не нужно использовать буфер набора данных SQLQuery1. А оператор Insert именно это делает. Полсмотри у него методы Execute и у TSQLConnection - метод ExecuteDirect.
Я сам именно с этими наборами не работаю - но по логике вещей именно они должны обеспечитвать прямое выполнение SQL запроса - без использования буфера.
А в твоём примере - посел заполнения каждой итерации необходимо делать POST а ApplyApdates - либо после всего цикла, либо переодически - через 1000 - 2000 итераций.
Но - это не самый лучший метод.


1. Ничего не помагает. Дошел даже до того, что уничтожал компоненты (.Free) - все бесполезно. И без разницы где ставить ApplyApdates, все равно один и тотже результат. Пока не закроешь приложение, память не очищается. Единственное что не пробовал, это использовать Insert into ...
2. Есть ли метод который очищает буфер набора данных.
3. имхо где-то ошибка, а желания разбираться с исходным кодом нет. Ведь при использовании .Free (.Destroy) должна была и память освободиться, занимаемая компонентом.

Добавлено спустя 31 минуту 27 секунд:
использование Insert into ... помогло решить это проблему
И добавление записей ускорилось в несколько раз.
Но все же иногда возникают ситуации, когда удобнее использовать другие способы добавления и редактирования записей.
nusya
новенький
 
Сообщения: 19
Зарегистрирован: 15.09.2008 12:58:15

Re: странное расходование памяти

Сообщение alexs » 09.01.2009 17:45:12

При массовой заливке данных - харнить заливаемые данные дополнительно в момент заливке на клиенте - бессмысленно. Поэтому для этой ситуации и надо напрямую использовать insert into и вызывать его через execsql.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 49

Рейтинг@Mail.ru