2012-02-08 16 views
5

Czytałem post na blogu (w tej chwili nie mogę znaleźć linku), w którym autor powiedział, że szybciej jest przypisać zmienną lokalną niż przy użyciu ADOQuery.FieldByName (' ... "). asString lub TSQLQuery.FieldByName (" ... "). asString, podczas analizowania całego zapytania z kilkoma tysiącami rekordów. Nie widzę różnicy międzyDelphi - FieldByName.AsString - dobra praktyka

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

i stosując bezpośrednio

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

Blog słupek nie mówi nic o rodzaju bazy danych lub wersji Delphi. Czy to rozwiązanie jest powiązane z jednym lub drugim (i nie mówię o mało znanych/niestandardowych systemach baz danych)?

+4

Te dwa fragmenty kodu wykona identycznie. –

+1

Czy możesz połączyć ten post? Być może coś źle zinterpretowałeś. – CodesInChaos

+0

Przypuszczam, że może być szybszy, jeśli potrzebujesz dostępu do tej samej wartości więcej niż raz (więc zamiast wywoływać 'FieldByName' wielokrotnie używałbyś zmiennej) – a1ex07

Odpowiedz

17

Nie ma zauważalnej różnicy w wydajności między nimi. Spodziewam się, co znaleźliście była różnica między

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

kontra

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

Jeśli tak, to ten ostatni jest bardziej efektywne, ponieważ FieldByName jest (stosunkowo) powolne działanie. Jeśli nie musisz wywoływać go więcej niż raz, nie wywołuj go więcej niż jeden raz.

+1

_Jeśli nie musisz wywoływać go więcej niż raz, nie dzwoń to więcej niż raz. Słuchaj! Słyszeć! –

+1

_ten drugi jest bardziej wydajny ..._ Jest także łatwiejszy do odczytania, debugowania i konserwacji. –

+2

dobrze wiedzieć. btw jego 2012 i wciąż nie ma iteratora dla zbioru danych, źle poczekać kolejne 10 lat. – none

5

Jaki sens jest taki:

  1. Jeśli masz klasy (takie jak TForm) nie lokalna funkcja, to albo uporczywie tworzyć pola można uniknąć kosztów wielokrotnego odnośnika (FieldByName).

  2. Jeśli nie używać trwałych pól (w DFM), można zrobić odnośnika raz przy starcie i uniknąć kosztów wielokrotnie szuka go, jeśli jest on stosowany albo (a) więcej niż jeden raz w kontekst pojedynczej funkcji, lub (b) gdzie można go wyszukać raz, gdy kwerenda jest wykonywana, i przechowywać w chronionym Polu obiektu, aby można było ponownie wykorzystać przez całe życie zapytania lub obiektu, jako stosowne.

Twój wymyślony przykład ma zero korzyści, ale wierzę, że powtarzające wyszukiwań pól kiedy te powtarzające wyszukiwań logiczne są zmarnowane, są chyba godnym rzeczą wspomnieć jako „marnotrawstwo”.

widzę kodu tak cały dzień, a to doprowadza mnie do szału:

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

Powyższy kod jest mniej czytelny takich powtórzeń i takich obaw czytelności, a także obawy o błędach sprawdzanie to dlaczego ja pozwoliłoby uniknąć wyżej i zamiast mieć fX:TField murawę:

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

end; 

teraz możemy napisać

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

Myślę, że ludzie martwią się zbytnio wydajnością i niewystarczającą jakością, a długie powtarzające się podekspozycje są oznaką "braku jakości" i "braku myśli" tak samo jak "braku troski o wydajność".

+0

_ Widzę kod taki jak ten cały dzień, a to napędza mnie nutami. Niestety, nie jesteś sam ... –

+1

Cześć Warren: +1. To, co nazywane jest statycznymi polami, nazywa się polami trwałymi (ponieważ pola są utrzymywane w DFM w przeciwieństwie do IDE zapominając o nich przez cały czas :-) –

+0

Dzięki Marjan. Naprawiony. –

1

Nazwa FieldByName służy do prostego wyszukiwania. jeśli chcesz wybrać więcej niż jedno pole. ten kod jest lepiej

// 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; 
Powiązane problemy