powodem jest fakt
User.where('status = 1').limit(1000)
zwraca ActiveRecord::Relation
która jest faktycznie jak poradzić sobie, a nie zapytanie. Railsy buforują zakres.
Jeśli chcesz buforować zapytanie, musisz użyć metody zapytania na końcu, na przykład #all
.
Rails.cache.fetch(key) do
User.where('status = 1').limit(1000).all
end
Uwaga nigdy nie jest dobry pomysł, aby buforować ActiveRecord obiekty. Buforowanie obiektu może spowodować niespójne stany i wartości. Zawsze należy buforować obiekty pierwotne, jeśli dotyczy. W takim przypadku rozważ buforowanie identyfikatorów.
ids = Rails.cache.fetch(key) do
User.where('status = 1').limit(1000).pluck(:id)
end
User.find(ids)
Można argumentować, że w tym przypadku wywołanie User.find
to zawsze wykonywany. To prawda, ale zapytanie za pomocą klucza głównego jest szybkie i omija problem, który opisałem wcześniej.Co więcej, buforowanie aktywnych obiektów rekordów może być kosztowne i szybko może skończyć się wypełnianie wszystkich pamięci Memcached za pomocą jednego pojedynczego wpisu pamięci podręcznej. Identyfikatory buforowania również zapobiegną temu problemowi.
thx. Jeśli mam model kategorii, może mieć mniej niż 100 rekordów, cache Category.all jest dobrym pomysłem? nie buforuje identyfikatora cateogry – tinylian
Czy najpierw zmienię Category.all na json i cache je w memcached? – tinylian
To bardzo ważny i subtelny problem; Właśnie zdaliśmy sobie sprawę, że ten problem wkradł się do naszej aplikacji - różnica między 'Foo.where (bar: 'fubar')' i 'Foo.where (bar: 'fubar'). Wszystko" jest zupełnie inne niż/t caching, i coś, co może łatwo i subtelnie wślizgnąć się do twojej bazy kodów. Sprawdzaj i regularnie sprawdzaj, jeśli korzystasz z buforowania. –