2012-02-08 36 views
5

He leído una publicación de blog (en este momento no puedo encontrar el enlace) donde el autor decía que es más rápido asignar una variable local que usar ADOQuery.FieldByName (' ... '). asString o TSQLQuery.FieldByName (' ... '). asString, al analizar una consulta completa con varios miles de registros. No veo la diferencia entreDelphi - FieldByName.AsString - buena práctica

var aLocalField: TField; 
.... 
aLocalField := ADOQuery.FieldByName('...'); 
.. 
ShowMessage(aLocalField.asString) 

y utilizando directamente

ShowMessage(ADOQuery.FieldByName('...').asString); 

Blog post no decir nada sobre el tipo de base de datos o la versión de Delphi. ¿Esta solución está relacionada con una u otra (y no estoy hablando de sistemas de bases de datos oscuros/personalizados)?

+4

Esos dos trozos de código llevará a cabo de forma idéntica. –

+1

¿Puedes vincular esa publicación? Quizás malinterpretaste algo. – CodesInChaos

+0

Supongo que puede ser más rápido si necesita acceder al mismo valor más de una vez (así que en lugar de llamar 'FieldByName' varias veces usa una variable) – a1ex07

Respuesta

17

No hay una diferencia de rendimiento notable entre los dos. Espero que lo que encontraron fue la diferencia entre

DataSet.First; 
while not DataSet.Eof do 
begin 
    ProcessValue(DataSet.FieldByName('Field').AsString); 
    DataSet.Next; 
end; 

frente

Field := DataSet.FieldByName('Field'); 
DataSet.First; 
while not DataSet.Eof do 
begin 
    ProcessValue(Field.AsString); 
    DataSet.Next; 
end; 

Si es así, este último es más eficiente porque FieldByName es un (relativamente) la función lenta. Si no necesita llamarlo más de una vez, no lo llame más de una vez.

+1

_Si no necesita llamarlo más de una vez, no llame es más de una vez. ¡Escucha! ¡Oír! –

+1

_ este último es más eficiente ..._ También es más fácil de leer, depurar y mantener. –

+2

es bueno saberlo. Por cierto, es 2012 y todavía no iterador para el conjunto de datos, simplemente esperar otros 10 años. – none

5

Lo que tiene sentido es la siguiente:

  1. Si usted tiene una clase (como por ejemplo un TForm) no es una función local, ya sea persistentemente crear los campos que evite el costo de las operaciones de búsqueda repetida (FieldByName).

  2. Si no utiliza los campos persistentes (en dfm), puede hacer una búsqueda una vez en tiempo de ejecución, y evitar el costo de buscarla repetidamente, si se usa ya sea (a) más de una vez el contexto de una función única, o (b) donde podría buscarse una vez cuando se ejecuta la consulta, y almacenarse en un campo protegido de un objeto, de modo que pueda reutilizarse durante la vida de la consulta o el objeto, según sea apropiado.

Su ejemplo artificioso tiene un beneficio cero, pero yo creo que las repetidas operaciones de búsqueda de campos cuando se desperdician estas búsquedas lógicas repetidas, son tal vez una cosa digna de mencionar como "desperdicio".

veo código así todo el día, y me vuelve loco:

procedure TSomething.DoSomething; 
begin 
    fDataset.FieldByName('X').AsString = fDataset.FieldByName('X').AsString+'Y'; 
end; 

El código anterior se hace menos legible por tales repeticiones, y tales preocupaciones de legibilidad, así como las preocupaciones de comprobación de errores son por qué evitaría lo anterior, y en lugar de tener un campo fX:TField:

TSomething = class(TBaseClass) 
    protected 
    fDataSet:TDataSet; 
    fX:TField; 

end; 

Ahora podemos escribir

fX.AsString := fX.AsString + 'Y'; 

Creo que las personas se preocupan demasiado por el rendimiento y no por la calidad, y las subexpresiones largas repetidas son un signo de "falta de calidad" y "falta de pensamiento" tanto como de "falta de preocupación por el rendimiento".

+0

_Veo código como este todo el día, y me vuelve loco. Por desgracia, no estás solo ... –

+1

Hola Warren: +1. A lo que se refiere como campos estáticos, creo que se los conoce como campos persistentes (porque los campos se conservan en el dfm en lugar de que el IDE se olvide de ellos todo el tiempo :-) –

+0

Gracias Marjan. Fijo. –

1

FieldByName use simple-search. si desea elegir más de un campo. este código es mejor

// 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; 
Cuestiones relacionadas