11

Dường như với tôi rằng bộ nhớ đệm mảnh và tải háo hức là - ít nhất là đôi khi - có phần mâu thuẫn với nhau. Hãy nói rằng tôi có một người dùng có nhiều bài viết mà mỗi người có nhiều ý kiến ​​mà lần lượt cũng có thể có nhiều ý kiến ​​và như vậy.Bộ nhớ đệm phân đoạn và tải mong muốn: Cách tận dụng tối đa cả hai thế giới?

Khi tôi phải hiển thị trang, tôi có thể chọn tải người dùng một cách háo hức, tất cả các bài đăng của cô ấy, tất cả nhận xét của họ, v.v. để tránh nhấn cơ sở dữ liệu n-1 lần. Hoặc Tôi có thể tải từng đối tượng một cách lười biếng và dựa vào bộ nhớ đệm của đoạn để chỉ truy vấn cơ sở dữ liệu cho các đối tượng mới hoặc đã bị thay đổi. Sử dụng cả bộ nhớ đệm của bộ đệm và tải dữ liệu có vẻ lãng phí, vì tôi có khả năng thực hiện một truy vấn rất phức tạp và khởi tạo rất nhiều đối tượng chỉ để sử dụng một phần nhỏ của chúng. Nhưng nếu tôi có một ứng dụng trong đó Người dùng có nhiều Foos có nhiều Thanh và nhiều thứ khác, nhưng trong đó mỗi Foo được tạo ra hoàn chỉnh với tất cả các Thanh và các đối tượng liên quan của nó cùng một lúc và từ sau đó không bao giờ thay đổi. Trong trường hợp đó, tôi muốn sử dụng bộ nhớ đệm mảnh cho Foos đã được trả lại, nhưng để sử dụng tải mong muốn khi tôi phải tải một Foo mới với tất cả các đối tượng liên quan của nó. Sau khi tất cả, không có gì để đạt được từ các bộ nhớ đệm ở mức độ chi tiết hơn.

Cách tốt nhất trong Rails để thực hiện việc này là gì? Tôi cho rằng tôi có thể thực hiện một truy vấn để chỉ nhận được các id của Foo, và sau đó thực hiện tìm kiếm rõ ràng với tải mong muốn khi tôi phải render từng Foo. Có cách nào tốt hơn/thanh lịch hơn/thành ngữ hơn để làm việc này không?

Trả lời

0

Bạn có thể sử dụng phương pháp fragment_exists? trong bộ điều khiển để ngăn không mong muốn tải tất cả các đối tượng khi chúng đã có trong bộ nhớ cache. Điều này sẽ không xảy ra ở lần đầu tiên trang được gọi.

Như thế này:

if fragment_exists? "my_cache_key_#{id}" 
    # load your object without eager loading here   
    else 
    # eager load your objects here   
    end 

Sau đó, trong giao diện sử dụng mảnh chaching:

<% cache("my_cache_key_#{@object.id}") do %> 
... 
... 
... 
<% end %> 

Điều đó sẽ làm điều đó cho bạn!

+0

Tôi nhận được điều này khi cố gắng truy cập fragment_exists? trong một bộ điều khiển '*** NoMethodError Ngoại lệ: phương thức không xác định \' fragment_exists? ' cho # ' –

+0

Ah, có vẻ như bạn muốn' fragment_exist? 'không có sự đa dạng hóa –

0

Xây dựng câu trả lời @daviddb cho Rails 4 cụ thể, tôi thấy cần thiết để skip_digest trong các chế độ xem như tạo lại MD5 Hash cho các mẫu trong bộ điều khiển để so sánh có vẻ hơi nhiều.

Ngoài ra, mà không tìm thấy đối tượng lần đầu tiên, nó sẽ rất khó khăn để có được những đối tượng với dấu thời gian sửa đổi lần cuối, vì vậy tôi tìm thấy nó hữu ích để làm một truy vấn ban đầu mà không .includes(:object1, :object2)

views/customers/show.html.slim (điều chỉnh cho khuôn mẫu ưa thích của bạn động cơ)

- cache['customers/show', @customer], skip_digest: true do 
    h1 
    = @customer.account.name 
    = render 'account_summary', account: @customer.account 
    = render 'account_details', transactions: @customer.account.transactions 
    ... 

controllers/customers_controller.rb

def show 
    customer = Customer.find(params[:id]) 
    if fragment_exist?(['customers/show', customer]) 
     @customer = customer 
    else 
     @customer = Customer.includes(account: :transactions).find(params[:id]) 
    end 
    end 

Lưu ý: Bằng cách đặt skip_digest: true bạn sẽ cần phải xóa bộ nhớ cache của bạn khi triển khai khi thay đổi chế độ xem này và bất kỳ phần nào mà nó phụ thuộc để đảm bảo bố cục mới của bạn được hiển thị đúng cách.

0

Tôi đã làm điều tương tự với bộ nhớ đệm bằng lambda. Dưới đây bạn có thể nhận được một ý tưởng. Vấn đề nó giải quyết - nhận được những người dùng phổ biến nhất là một hoạt động nặng và yêu cầu> 5 giây. Nhưng với lambda bạn có thể cache danh sách người dùng.

controller: 
def index 
@users = -> { User.by_rating } 
end 

view: 
= cache "rating-list", expires_in: 1.day do 
    - @users.call.each do |user| 
    = render user 
Các vấn đề liên quan