Pra*_*oya 6 caching ruby-on-rails ruby-on-rails-3 russian-doll-caching cache-digests
根据我对Rails中俄罗斯娃娃缓存的理解,当我们进行RDC(俄罗斯娃娃缓存)时,这对于急切的加载相关对象或对象列表是有害的,因为在RDC中我们只是从数据库加载顶级对象,并查找它缓存渲染的模板和服务.如果我们要急切加载相关的对象列表,如果缓存不是陈旧的话,这将是无用的.
我的理解是否正确?如果是,我们如何确保我们在第一次调用时急切加载所有相关对象,以免在第一次加载(缓存不热)时支付N + 1个查询的成本.
正确 - 当加载具有许多关联的集合或复杂对象时,可以通过快速、简单的调用来避免昂贵的急切加载所有对象和关联的调用。
缓存的 Rails 指南确实有一个很好的例子,但是,它被分割了一些。查看缓存集合的常见用例(即 Rails 中的索引操作):
<% cache("products/all-#{Product.maximum(:updated_at).try(:to_i)}") do %>
All available products:
<% Product.all.each do |p| %>
<% cache(p) do %>
<%= link_to p.name, product_url(p) %>
<% end %>
<% end %>
<% end %>
Run Code Online (Sandbox Code Playgroud)
此(精简)示例执行 1 个简单的数据库调用Product.maximum(:updated_at),以避免执行成本更高的调用Product.all。
对于冷缓存(第二个问题),通过急切加载关联对象来避免 N+1 很重要。然而,我们知道我们需要执行这个昂贵的调用,因为集合的第一次缓存读取丢失了。在 Rails 中,这通常是使用includes. 如果 aProduct属于多个Orders,则类似:
<% cache("products/all-#{Product.maximum(:updated_at).try(:to_i)}") do %>
All available products:
<% Product.includes(:orders).all.each do |p| %>
<% cache(p) do %>
<%= link_to p.name, product_url(p) %>
Bought at:
<ul>
<% p.orders.each do |o| %>
<li><%= o.created_at.to_s %></li>
<% end %>
</ul>
<% end %>
<% end %>
<% end %>
Run Code Online (Sandbox Code Playgroud)
在冷缓存情况下,我们仍然对集合和每个成员进行缓存读取,但是,在部分热缓存情况下,我们将跳过对部分成员的渲染。请注意,此策略依赖于更新关联对象时Product正确设置的关联。touch
更新:这篇博文描述了一种更复杂的模式,以进一步优化部分缓存集合的构建响应。它不是重建整个集合,而是批量获取所有可用的缓存值,然后对剩余值进行批量查询(并更新缓存)。这在几个方面很有帮助:批量缓存读取比 N+1 缓存读取更快,并且对数据库进行批量查询来构建缓存也更小。
| 归档时间: |
|
| 查看次数: |
622 次 |
| 最近记录: |