piątek, 22 kwietnia 2011

count vs length vs size w Rails

W Ruby zarówno #length jak i #size to synonimy podawania wielkości tablicy bądź tablicy asocjacyjnej.
W Railsowym ActiveRecord wygląda na to, że są trzy drogi podawania wielkości asocjacji:
  1. firm.customers.count - wykonuje standardowe zapytanie SQL COUNT. Co ciekawe można podawać warunki podzbioru. Na przykład :conditions => {:customer_name = "Nowak"}. Jeśli nastąpiło wcześniejsze zapytanie SQL COUNT, wtedy #count pokaże zawartość cache, jeśli nie, wykona nowe zapytanie.
  2. firm.customers.length - zawsze ładuje całą asocjację do pamięci, potem ją zlicza i podaje wielkość. Ważne jest, że ta metoda nie wymusza zapytania, jeśli zawartość asocjacji była już pobierana.
  3. firm.customers.size - ta metoda działa w przybliżeniu jako kombinacja dwóch powyższych. Jeśli acocjacja była już pobierana podaje po prostu jej wielkość i tyle. Jeśli nie była pobierana, to wykonuje #count z punktu 1.
Piszę o tym, bo czasami można się naciąć jeśli oczekuje się bardzo szybkiej operacji, a trwa ona zdecydowanie dłużej niż spodziewana. No i to cachowanie...
Więc właśnie. Dwa słowa odnośnie cachowania. Rozważmy następujące przypadki:
Przypadek 1:
@firm = Firm.find(params[:id]) 
@amount_customers_in_firm = @firm.customers.size 
#tu nastąpi zapytanie do bazy

Przypadek 2:
@firm = Firm.find(params[:id])
@customers = @firm.customers 
@amount_customers_in_firm = @firm.customers.size 
#tu zwrócona zostanie ilość rekordów pobrana z cache

Przypadek 3:
@firm = Firm.find(params[:id])
@customers = @firm.customers 
. # tu
. # jakieś
. # gęste
. # operacje
. # na rekordach
@amount_customers_in_firm = @firm.customers(true).size 
#tu wymuszam ponowne zapytanie do bazy z pominięciem cache

Więcej na temat cachowania asocjacji w Rails guides.
Zaś ogólnie o cachowaniu zawodowy artukuł z thewebfellas.