powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Утечка памяти при работе с DataSet
25 сообщений из 69, страница 1 из 3
Утечка памяти при работе с DataSet
    #39555982
Фотография шК0ДЕР
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день. К дб гриду (TDBGridEh - компонент EhLib 8.0 build 8.0.023) прикручен датасет. FetchAll := False естественно, т.к записей возвращается много, до 100к. Имеется функционал по выводу данных из грида в эксель(самописный). Для этого нужно знать общее кол-во записей в датасете, которое узнаю с помощью следующей процедуры
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
procedure GetDataSetRows;
var
  bm: TBookmark;
begin
  with FDataSet do
  begin
    DisableControls;
    bm := GetBookmark;
    First;
    FDataSetRows := 0;
    While not Eof do
    begin
      Inc(FDataSetRows);
      Next;
    end;
    GotoBookmark(bm);
    FreeBookmark(bm);
    EnableControls;
  end;
end;


Проблема возникает в цикле,
Код: pascal
1.
2.
3.
4.
5.
While not Eof do
    begin
      Inc(FDataSetRows);
      Next;
    end;

приложение съедает память до 1 гб (когда FDataSetRows инкрементируется до ~40к) и завершает работу с ошибкой "Out of memory". Если записей в датасете немного, то все работает без ошибок.

Подскажите, как можно исправить утечку или посчитать кол-во записей в датасете?
Вариант с возвращением кол-ва записей в запросе с сервера не лучший, т.к процедура по печати отчетов универсальная, а запросов для этих самых отчетов больше тысячи, накладно все их дописывать
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39555983
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
шК0ДЕР,

Это не утечка, а просто не хватает памяти для такого огромного буффера.
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39555985
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
шК0ДЕР,

Выход один:
1. Для получения каунта использовать отдельно select count(*) from;
2. В отчет выводить постранично (скажем, по 1000 записей). (что-то типа select first 1000 step 5000)
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39555987
Фотография шК0ДЕР
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Этого то я и боялся...
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39555989
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хотя подожди... При
шК0ДЕРFetchAll := False
Такого может и не должно быть. Может действительно утечка в компонентах доступа или еще где?
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39555992
Фотография шК0ДЕР
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тоже странным показалось, компоненты проверил, вроде чисто. Смотрел при отладке в диспетчере задач, память утекает именно при переборе записей датасета. В Locate() кстати та же проблема.
Пытался решить вот чем:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
DBGrid.DataSource.DataSet := nil;
While not Eof do
begin
   Inc(FDataSetRows);
   Next;
end;
DBGrid.DataSource.DataSet := FDataSet;


Код: pascal
1.
2.
3.
4.
5.
6.
7.
DBGrid.DataSource.Enabled := False;
While not Eof do
begin
   Inc(FDataSetRows);
   Next;
end;
DBGrid.DataSource.Enabled := True;


заменяя цикл на
Код: pascal
1.
2.
Last;
FDataSetRows := RecNo;


Для эксперемента прописал Refresh в цикле, память, потребляемая приложением сбрасывается до обычной - 8к.
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39555994
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
шК0ДЕРзаменяя цикл на
Код: pascal
1.
2.
Last;
FDataSetRows := RecNo;

Если в твоих компонентах работает RecNo после Last, зачем проктология с циклом тогда.
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39556002
Фотография шК0ДЕР
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock, код не мой. В любом случае при выполнении метода Last(который так и не выполняется до конца) происходит та же котовасия с памятью. Компонент TOracleDataSet, DOA
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39556008
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
шК0ДЕР,

Может это компонент и не умеет при отключенном FetchAll буффер определенного размера только помнить.
А с другой стороны, вряд ли такое возможно. Ведь всегда должны быть возможны Prev или First. А как такое сделать на уровне базы? Наверно никак. Unfetch какой-нибудь если и есть где-то, то не везде и не всегда может сработать.
Т.ч. Только переделывать.
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39556028
Фотография шК0ДЕР
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock, разобрался как кол-во строк подсчитывалось. В компоненте было отключено свойство CountAllRecords и ReсordCount возвращал кол-во видимых записей из грида. При включенному свойстве возвращается общее кол-во записей.
Но проблема осталась. При самой печати данных происходит перебор записей датасета. Отчет недоформировывается
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39556031
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это нормальное, обычное поведение. Наборы данных обычно держат все данные в памяти. Вот представьте - что всю выборку из базы всунули в память + обвязка (т.к данные в памяти не в raw же хранить).

авторВедь всегда должны быть возможны Prev или First.

Проблема даже не в Prev/First, как раз таки Prev/First сделать не проблема. Проблема в том, что вся выборка может понадобится для отображения в гриде и как тогда по-другому сделать? Кроме как тащить весь набор в память.

Код: pascal
1.
2.
3.
4.
5.
While not Eof do
    begin
      Inc(FDataSetRows);
      Next;
    end;



Это тоже самое, что FetchAll, это FetchAll и есть.

авторПодскажите, как можно исправить утечку или посчитать кол-во записей в датасете?

1. Это не утечка памяти. Это обычная, нормальная работа. Наборы именно так и работают.
2. Если не нужно отображать данные в гриде, то можно взять набор, который не тащит все данные в память, а выбирает только текущую запись. В случае IBX, например, это TIBSQL. В других наборах компонент может быть по-разному: от отдельной компоненты до опций в пределах одной.
3. Намного лучше вместо того, что бы считать количество записей на клиенте посчитать их сервером, отдав ему соответствующий запрос (select count(some_field) as counter from database).
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39556034
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
4. Если же нужно отображать набор в гриде - то либо ограничивать количество записей в наборе, либо переходить на 64х.
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39556039
Фотография шК0ДЕР
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
makhaon, с кол-вом записей уже разобрался. Проблема теперь при печати отчета. Хотя способ аналогичен...
Код: pascal
1.
2.
3.
4.
5.
While not DataSet.Eof do
begin
   //печать данных
   Next;
end;

Есть еще какие-либо идеи кроме печати данных по частям?
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39556050
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
шК0ДЕР,

авторпереходить на 64х
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39556053
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
сделать отдельный набор именно для печати, как я говорил:
"можно взять набор, который не тащит все данные в память, а выбирает только текущую запись. В случае IBX, например, это TIBSQL"
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39556075
schi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
шК0ДЕРmakhaon, с кол-вом записей уже разобрался. Проблема теперь при печати отчета. Хотя способ аналогичен...
Код: pascal
1.
2.
3.
4.
5.
While not DataSet.Eof do
begin
   //печать данных
   Next;
end;

Есть еще какие-либо идеи кроме печати данных по частям?

Использовать unidirectional dataset, например
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39556107
LSV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще-то чтобы зачитать весь ДС (кот. зачитан не целиком), достаточно стать в его конец (last), в потом вернуться.
Тогда станет известно кол-во записей. И можно начинать экспорт.
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39556110
schi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LSVВообще-то чтобы зачитать весь ДС (кот. зачитан не целиком), достаточно стать в его конец (last), в потом вернуться.
Тогда станет известно кол-во записей. И можно начинать экспорт.

Попробуй на больших объемах, тебе понравится.
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39556140
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schiИспользовать unidirectional dataset, напримерИли вообще не датасет. Что-то типа TIBSQL
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39556154
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Будь я твоим руководителем, я бы заставил тебя пролистать все 100к строк
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39556200
LSV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schiLSVВообще-то чтобы зачитать весь ДС (кот. зачитан не целиком), достаточно стать в его конец (last), в потом вернуться.
Тогда станет известно кол-во записей. И можно начинать экспорт.

Попробуй на больших объемах, тебе понравится.А то я не пробовал... :)
Все равно это придется грузить, чтобы экспортировать. Объем вычислений будет одинаковым.
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39556205
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock
Может это компонент и не умеет при отключенном FetchAll буффер определенного размера только помнить.
А с другой стороны, вряд ли такое возможно. Ведь всегда должны быть возможны Prev или First. А как такое сделать на уровне базы? Наверно никак. Unfetch какой-нибудь если и есть где-то, то не везде и не всегда может сработать.
Т.ч. Только переделывать.

Без привязки к конкретному вопросу вставлю свои 5 копеек - есть такая штука как TIB_Cursor (библиотека IBObjects) - там буфер выделяется ровно на одну запись из БД и сам TIB_Cursor умеет только Next(). Самое то для ТС, если найдутся аналоги.
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39556218
Фотография JayDi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Там в этой базе файлы в блобах хранятся что ли? Как-то многова-то веса (аж гигабайт) для всего 40к строчек.
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39556277
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JaDiТам в этой базе файлы в блобах хранятся что ли? Как-то многова-то веса (аж гигабайт) для всего 40к строчек.Блобы как раз не тянутся. Может, строки длинные
...
Рейтинг: 0 / 0
Утечка памяти при работе с DataSet
    #39556278
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А может и SELECT* убрать можно и поможет.
...
Рейтинг: 0 / 0
25 сообщений из 69, страница 1 из 3
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Утечка памяти при работе с DataSet
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]