Reputation: 12584
I've read an blog post(at this moment I can't find the link) where the author was saying that is faster to assign a local variable than using ADOQuery.FieldByName('...').asString or TSQLQuery.FieldByName('...').asString, when parsing an entire query with several thousands of records. I don't see the difference between
var aLocalField: TField;
....
aLocalField := ADOQuery.FieldByName('...');
..
ShowMessage(aLocalField.asString)
and by using directly
ShowMessage(ADOQuery.FieldByName('...').asString);
Blog post did not say anything about the database type or Delphi version. Is this solution related to one or another(and I'm not talking about obscure/custom database systems)?
Upvotes: 5
Views: 27062
Reputation: 68922
What makes sense is this:
If you have a CLASS (such as a TForm) not a local function, you either persistently create the fields you avoid the cost of repeated lookup (FieldByName).
If you don't use persistent fields (in a dfm), you could do a lookup once at runtime, and avoid the cost of repeatedly looking it up, if it is used either (a) more than once in the context of a single function, or (b) where it could be looked up once when the query is executed, and stored in a protected Field of an object, so that it can be reused for the life of the query or the object, as appropropriate.
Your contrived example has zero benefit, but I believe that repeated lookups of Fields when these repeated logical lookups are wasted, are perhaps a worthy thing to mention as "wasteful".
I see code like this all day, and it drives me nuts:
procedure TSomething.DoSomething;
begin
fDataset.FieldByName('X').AsString = fDataset.FieldByName('X').AsString+'Y';
end;
The above code is made less readable by such repetitions, and such readability concerns, as well as error checking concerns are why I would avoid the above, and instead have a fX:TField
field:
TSomething = class(TBaseClass)
protected
fDataSet:TDataSet;
fX:TField;
end;
Now we can write
fX.AsString := fX.AsString + 'Y';
I think people worry too much about Performance and not enough about quality, and long repeated subexpressions are a sign of "lack of quality" and "lack of thought" just as much as of "lack of concern for performance".
Upvotes: 5
Reputation: 3983
FieldByName use simple-search. if you want to choice more than one field. this code is better
// Same Text in StrUtils(unit)
for I:=0 to DataSet.Fields.Count-1 do
begin
if SameText( DataSet.Fields[I].FieldName,'Field1') then
Field1:=DataSet.Fields[I]
else if SameText( DataSet.Fields[I].FieldName,'Field2') then
Field2:=DataSet.Fields[I];
end;
DataSet.First;
while not DataSet.Eof do
begin
ProcessValue(Field.AsString);
DataSet.Next;
end;
Upvotes: 1
Reputation:
There is no noticeable performance difference between the two. I expect what you found was the difference between
DataSet.First;
while not DataSet.Eof do
begin
ProcessValue(DataSet.FieldByName('Field').AsString);
DataSet.Next;
end;
versus
Field := DataSet.FieldByName('Field');
DataSet.First;
while not DataSet.Eof do
begin
ProcessValue(Field.AsString);
DataSet.Next;
end;
If so, the latter is more efficient because FieldByName
is a (relatively) slow function. If you don't need to call it more than once, don't call it more than once.
Upvotes: 17