25

W Railsach, zarówno find_each i where są używane do pobierania danych z bazy danych obsługiwanych przez ActiveRecord.W Railsach, jaka jest różnica między find_each i gdzie?

Możesz przekazać swój stan kwerendy where, jak:

c = Category.where(:name => 'Ruby', :position => 1) 

I można przekazać wielkości wsadu do find_each, jak:

Hedgehog.find_each(batch_size: 50).map{ |p| p.to_json } 

Ale jaka jest różnica między poniższym kodzie 2?

# code 1 
Person.where("age > 21").find_each(batch_size: 50) do |person| 
    # processing 
end 

# code 2 
Person.where("age > 21").each do |person| 
    # processing 
end 

Czy partia kodu 1 pobiera 50 krotek za każdym razem, a kod 2 odzyskuje wszystkie krotki w tym samym czasie? Bardziej szczegółowe wyjaśnienia są mile widziane.

Moja opinia jest taka:

  1. zarówno where i find_each może być używany do partii wyszukująca, ale przy użyciu find_each użytkownik może definiować wielkość wsadu.
  2. find_each nie obsługuje warunków zapytania o przekazanie.

Proszę mnie poprawić, jeśli moje zrozumienie jest błędne.

Odpowiedz

38

Aktywna relacja rekordów nie powoduje automatycznego załadowania wszystkich rekordów do pamięci.

Po wywołaniu #each wszystkie zapisy zostaną załadowane do pamięci. Po wywołaniu #find_each, rekordy będą ładowane do pamięci w partiach o danym rozmiarze wsadu.

Tak więc, gdy zapytanie zwróci liczbę rekordów, które będą zbyt dużą ilością pamięci dla dostępnych zasobów serwera, użycie #find_each będzie doskonałym wyborem.

Jest to zasadniczo jak używanie leniwe wyliczenie ruby ​​#to_enum#lazy z #each_slice, a następnie #each (bardzo wygodne).

+0

Więc kod 1 może wykonywać SQL wiele razy (w zależności od rozmiaru rekordów i wielkości partii), kod 2 wykonuje tylko SQL raz? – coderz

+1

Tak, to moje zrozumienie. Jeśli spojrzysz na swój log rozwoju lub spojrzysz na wynik SQL w konsoli rails, zobaczysz coś w rodzaju 'Users.for_each (batch_size) {| u | } "SELECT" użytkowników "." * "OD" użytkowników "WHERE (" users "." Id "> 51)" SELECT "użytkowników". "*" FROM "users" WHERE ("users". "Id" > 51) LIMIT 50' ... i tak dalej – jphager2