2013-06-09 12 views
9

W home_controller moich Rails 4 aplikacji, mogę wykonać kwerendy niestandardowe sql i zapisać wyniki do instancji zmiennejCzy można buforować niestandardowe zapytania SQL w Railsach?

@studentscoring = ActiveRecord::Base.connection.execute sql_string_student 

I wtedy, po ustawieniu buforowanie true w rozwoju config config.action_controller.perform_caching = true i ponownego uruchomienia aplikacji, należy ustawić buforowanie wokół odpowiedniej zmiennej w widoku.

<% cache @studentscoring do%> 
    <% for lawyer in @studentscoring %> 
    <div class="span2"> 
     <div class="row"> 
     <%= tiny_gravatar_for lawyer['name'], lawyer['email'] %> 

     </div> 
     ...... #code ommitted 
    </div> 

    <% end %> 
    <% end %> 

Odświeżanie przeglądarki trzykrotnie pokazuje, że zapytanie jest prowadzony trzy oddzielne razy i ostatni bieg zapytania faktycznie ma .7ms dłuższe niż pierwszy, więc jestem zakładając buforowanie nie działa, czy jestem nie robię tego poprawnie :). Czy możesz mi powiedzieć, co robię źle?

Nie będąc ekspertem według jakichkolwiek standardów, nie rozumiem, jak można włączyć buforowanie z widoku z składnią% cache ... do%> <%, ponieważ do czasu wczytywania widoku nie ma Zapytania kontrolera zostały już uruchomione, dlatego jest zbyt późno, aby Rails mógł użyć kopii z pamięci podręcznej?

z logów serwera ...

Pierwszy

(1.1ms) with cte_scoring as (
select 
users.id, users.name, users.email, 
(select Coalesce(sum(value),0) from answer_votes where (answer_votes.user_id = users.id) AND (created_at >= Current_Date - interval '7 day')) + 
(select Coalesce(sum(value),0) from best_answers where (best_answers.user_id = users.id) AND (created_at >= Current_Date - interval '7 day')) + 
(select Coalesce(sum(value),0) from contributions where (contributions.user_id = users.id) AND (created_at >= Current_Date - interval '7 day')) total_score 
from 
users 
where 
users.student = 'true') 

select id, 
name, 
email, 
total_score 
from cte_scoring 
order by total_score desc 
limit 5 

3-ty

(1.8ms) with cte_scoring as (
select 
users.id, users.name, users.email, 
(select Coalesce(sum(value),0) from answer_votes where (answer_votes.user_id = users.id) AND (created_at >= Current_Date - interval '7 day')) + 
(select Coalesce(sum(value),0) from best_answers where (best_answers.user_id = users.id) AND (created_at >= Current_Date - interval '7 day')) + 
(select Coalesce(sum(value),0) from contributions where (contributions.user_id = users.id) AND (created_at >= Current_Date - interval '7 day')) total_score 
from 
users 
where 
users.student = 'true') 

select id, 
name, 
email, 
total_score 
from cte_scoring 
order by total_score desc 
limit 5 

Aktualizacja

Dzienniki pokazać, że czyta fragment (po przeprowadzeniu powyższych zapytań są uruchamiane), dlaczego więc kwerendy miałyby inne czasy, a późniejsza kwerenda wolniej? Sądziłem, że zapytania nie zostaną w ogóle uruchomione, jeśli istnieje fragment do odczytania.

Read fragment views/id/75/name/Retarded Student/email/[email protected]/total_score/0/id/83/name/Jim Beam/email/[email protected]/total_score/0/id/79/name/Weird Student/email/[email protected]/total_score/0/id/80/name/VegetableSTudent/email/[email protected]/total_score/0/c9638e467bfd0fbf5b619ab411182256 (0.3ms) 
+0

Dobre pytanie! Pamięć podręczna ActiveRecord wydaje się być bardzo popularna w plemionach - ciężko było mi znaleźć wyraźną dokumentację, która odpowie na twoje pytanie. – RyanWilcox

Odpowiedz

7

Cache wyniki zapytania w kontrolerze. można odczytać lub zapisać z powrotem do pamięci podręcznej w jednym wywołaniu (czyli ustawić dane w pamięci podręcznej, jeśli jeszcze nie istnieje)

def index 
    @studentscoring = Rails.cache.fetch("your_cache_key", :expires_in => 5.minutes) do 
    ActiveRecord::Base.connection.select_rows(sql_string_student) 
    end 
end 

Więc powyżej najpierw sprawdzi pamięć podręczną dla "your_cache_key" i jeśli dane istnieje, zwróci go z pamięci podręcznej. Jeśli nie istnieje, to blok zostanie wykonany i zostanie ustawiony w pamięci podręcznej.

+0

to jest buforowanie akcji? Jeśli tak, czy nie jest prawdą, że nie jest zalecany w Railsach 4? Tak czy inaczej, "your_cache_key" jest czymś, co ustawiam arbitralnie lub czy jest generowana szyna? Dzięki za pomoc. – Leahcim

+0

Kiedy mówię "nie polecam w szynach 4", miałem na myśli fakt, że dodano skróty do pamięci podręcznej, aby wyeliminować konieczność ustawiania numerów wersji pamięci podręcznych. Nie jestem pewien, czy to właśnie twoje odwołanie z "twój_cache_key" – Leahcim

+0

To nie jest buforowanie akcji –

7

z pamięci podręcznej perspektywy ActiveRecord:

Sposób Rozumiem to, że cache zapytań ActiveRecord jest za zamówienie internetowej. Oznacza to, że jeśli dwukrotnie uruchomiłeś zapytanie SQL w tym samym żądaniu, które wykorzystywałoby pamięć podręczną, ale pamięć podręczna zostanie wyczyszczona na końcu każdego żądania.

Źródło: ActiveRecord::QueryCache middleware source

(wierzę, że `połączenia ActiveRecord :: Base.execute są buforowane w ogóle, podobnie jak zapytaniami zrobić z ActiveRecord kwerendy API)

Jeśli tylko chcesz raz wykonaj zapytanie dotyczące cyklu życia aplikacji (lub raz na kilka godzin), możesz użyć innego interfejsu Rails API: buforującego interfejsu API do przechowywania pamięci podręcznej w systemie plików, w pamięci, w pamięci memcache lub w niestandardowym magazynie. The Rails Guide on Caching/Cache Stores.

Jeśli zdecydujesz się na użycie Rails.cache, Heroku Dev Center on Caching Strategies ma kilka przykładów kodu pokazujących, jak wygląda interfejs API dla Rails.cache. Jest dość łatwy w użyciu.

Dlaczego cache fragment nie działa jak można oczekiwać

Wezwanie cache Państwa zdaniem oznacza to, że jesteś definiowanie pamięci podręcznej fragmentu. (patrz Rails Guide on Caching/Fragment caching section). Spowoduje to buforowanie danych wyjściowych HTML w widoku, co widać w dzienniku.

Ale pamięć podręczna fragmentów dotyczy tylko kodu HTML. Po wykonaniu zapytania i przypisaniu wyników do @studentscoring robisz to w kontrolerze (prawda?) Przed wykonaniem widoku.

Zapytania ActiveRecord są zwykle leniwy - wykonanie jest opóźnione, aż dane będą naprawdę potrzebne, np. Powtarzanie rekordów - więc Twoja sztuczka mogła zadziałać podczas korzystania z interfejsu API zapytań ActiveRecord. Jednak domyślam się, że zapytania ActiveRecord::Base.execute nie są leniwe. Nie mogę tego udowodnić, ale możesz przeprowadzić eksperyment.

Tak więc pamięć podręczna fragmentów może być używana, ale już zapłaciłeś cenę za zapytanie w kontrolerze.

Powiązane problemy