Memory consumption inserting records into a table
Posted: Mon 12 Jan 2009 20:57
Inserting large numbers of records into a table using TSmartQuery causes large amounts of memory to be consumed. Depending on the number of records to be put into the table, the memory can grow without limit. Once the smartquery has been closed, the memory used is not released. I found that the memory is not in fact released until FreeOCI() is called during application finalization called in OraCalls.pas.
The following is sample code that can be setup to illustarte the problem:
//Sample code to illustrate the problem. Caling TestMemIssue(5000) will cause the memory
//on my computer to grow by 30 MB
Other observations I have made.
1.) Calling: TestMemIssue(5000) and then immediately calling TestMemIssue(5000) again seems to re-use the same memory and does not increase memory.
2.) Calling: TestMemIssue(5000) and then immeidately calling TestMemIssue(10000) will cause the memory to grow very large.
Am I doing something incorrect to have so much memory being used? I am creating data conversion applications that are inserting large numbers of records using this sort of process and I am coming up with EOutOfMemory exceptions. What can I do to fix this or is this a bug in ODAC?
The following is sample code that can be setup to illustarte the problem:
Code: Select all
CREATE TABLE TESTTABLE(
OBJECTID NUMBER(9),
LIDAR_COLL DATE,
LIDAR_DEL DATE,
LINE_NUMBE VARCHAR2(254),
LINE_NAME VARCHAR2(100),
STRA VARCHAR2(254),
STRB VARCHAR2(254),
STR_DESIGN VARCHAR2(254),
LOC_ZONE VARCHAR2(254),
ALERT_NUM VARCHAR2(254),
LIDAR_DIST NUMBER(19,11),
HEIGHT NUMBER(19,11),
HEIGHT_85 FLOAT(126),
DENSITY FLOAT(126),
AREA FLOAT(126),
LAT NUMBER(19,11),
LON NUMBER(19,11),
SEL_ID NUMBER(9),
SEL_FLAG VARCHAR2(50),
TEMP_FLAG VARCHAR2(10),
GEOM SDO_GEOMETRY,
WORKZONE VARCHAR2(3),
COMPANY VARCHAR2(30),
IMPORTDATE DATE,
FALLINHEIGHT NUMBER,
RECID NUMBER);
//on my computer to grow by 30 MB
Code: Select all
procedure TMainForm.TestMemIssue(ACount: Integer);
var
lInc: Integer;
x: Integer;
lLocation: Double;
lOraSession: TOraSession;
lSmartQuery: TSmartQuery;
begin
lOraSession:=TOraSession.Create(nil);
lSmartQuery:=TSmartQuery.Create(nil);
try
lOraSession.LoginPrompt:=false;
lOraSession.Password:=fPassword;
lOraSession.Username:=fUserID;
lOraSession.Options.Net:=false;
lOraSession.Server:=fOracleServerAddress;
lOraSession.Open;
lOraSession.AutoCommit := false;
fTransIncCount:=0;
fInTransAction:=False;
lSmartQuery.Session:=lOraSession;
lSmartQuery.ObjectView:=true;
lSmartQuery.Debug := False;
lSmartQuery.close;
lSmartQuery.SQL.clear;
lSmartQuery.SQL.add('select T.*, T.ROWID from TESTTABLE T where 1=0'); // to get the fields
lSmartQuery.open;
lInc:=0;
lOraSession.StartTransaction;
while lInc<ACount do
begin
lSmartQuery.Append;
with lSmartQuery do
begin
FieldByName('LIDAR_COLL').AsDateTime := 39644;
FieldByName('LIDAR_DEL').AsDateTime := 39762;
FieldByName('LINE_NUMBE').AsString := '246622';
FieldByName('LINE_NAME').AsString := 'Aman - Keemmer';
FieldByName('STRA').AsString := '232-274';
FieldByName('STRB').AsString := '232-275';
FieldByName('STR_DESIGN').AsString := 'AEP_Number';
FieldByName('LOC_ZONE').AsString := 'P1';
FieldByName('ALERT_NUM').AsString := '246622-P1-15069';
FieldByName('LIDAR_DIST').AsFloat := 58.5629;
FieldByName('HEIGHT').AsFloat := 48.5235;
FieldByName('HEIGHT_85').AsFloat := 47.4409;
FieldByName('DENSITY').AsFloat := 84.62;
FieldByName('AREA').AsFloat := 110.384;
FieldByName('LAT').AsFloat := 39.3819326378;
FieldByName('LON').AsFloat := -81.1729436286;
FieldByName('WORKZONE').AsString := 'P1';
FieldByName('IMPORTDATE').AsDateTime := 39822.3565162037;
FieldByName('RECID').AsInteger := 0;
end;
lSmartQuery.GetObject('GEOM').AttrAsInteger['SDO_GTYPE']:=2003;
with lSmartQuery.GetObject('GEOM').AttrAsArray['SDO_ELEM_INFO'] do
begin
ItemAsInteger[0]:=1;
ItemAsInteger[1]:=3;
ItemAsInteger[2]:=1;
end;
lLocation:=45;
with lSmartQuery.GetObject('GEOM').AttrAsArray['SDO_ORDINATES'] do
begin
for x:=0 to 71 do
begin
ItemAsFloat[x]:=lLocation;
lLocation:=lLocation+0.0000001;
end;
end;
lSmartQuery.Post;
inc(lInc);
if lInc mod 500=0 then
begin
lOraSession.Commit;
lOraSession.StartTransaction;
end;
end;
lOraSession.Commit;
lOraSession.Close;
finally
lSmartQuery.Free;
lOraSession.Free;
end;
ShowMessage('done');
end;
1.) Calling: TestMemIssue(5000) and then immediately calling TestMemIssue(5000) again seems to re-use the same memory and does not increase memory.
2.) Calling: TestMemIssue(5000) and then immeidately calling TestMemIssue(10000) will cause the memory to grow very large.
Am I doing something incorrect to have so much memory being used? I am creating data conversion applications that are inserting large numbers of records using this sort of process and I am coming up with EOutOfMemory exceptions. What can I do to fix this or is this a bug in ODAC?