MongoDB mongoid 中的主从表缓存

lukefan · 2014年01月14日 · 最后由 lukefan 回复于 2014年01月14日 · 8283 次阅读

我在 mongoid 中有三张表。 resource、item、photo 其中 resource 是主表,item 和 photo 都是 resource 的子表。

在 resource.rb 中加入了

default_scope order_by(:updated_at.desc).includes(:photos)

之后,取出 resource 之后,photo 的取出就不会再占用时间了。

我在 item.rb 中加入了

scope :latest, where(:latest => true).limit(2)

之后,应该怎么缓存这部分数据呢? 我希望取出一批 resource 之后,就不要再逐条的去读取 items 了。

尝试了这样的代码:

default_scope order_by(:updated_at.desc).includes(:photos) do
    items.latest.cache
  end

但是每次读取 20 条 resource,每个 resource 两个 photo,两个 item 的情况下依然要用 3 秒钟。 有什么办法可以处理一下吗?

直接 embed 两个最新 item 进 resource?

去掉 include,父级元素片段缓存。

#2 楼 @Rei 可以详细些吗?

#1 楼 @aptx4869 embed 进去的东西,是不是 load 的时候,直接装载?效率很高?

#3 楼 @lukefan 由于不知道你的内容怎么展示,我用 post 为例

<% @posts.each do |post| %>
  <div class="post">
    <b><%= post.user.name %></b>
    <%= format_post psot.content %>
  </div>
<% end %>

这里优化方法不是在 @posts 查询 includes(:user),而是应该加上片段缓存

<% @posts.each do |post| %>
  <% cache post do %>
    <div class="post">
      <b><%= post.user.name %></b>
      <%= format_post psot.content %>
    </div>
  <% end %>
<% end %>

这样每次只要查询 @posts,虽然 post 内容在渲染时候需要查询 user,但之后就会缓存起来。反而,如果用了 includes,无论有没有缓存,每次查询 @posts 的时候都要查 user,这是不必要的消耗。

includes 对关系数据库有用,比如 todolists has_many todos,展示 todolists 内容的时候总是需要查询 todos 的,用 includes 可以用 join 把两次查询合成一次,但 mongodb 没有 join,所以没有什么意义。

includes 不是魔法,看看 logger 它是通过什么查询语句实现的。

#5 楼 @Rei 非常感谢,我是做的整页的缓存,但是第一次 render 的时候,非常缓慢,感觉无法忍受。 所以希望能够找一种方法,来提速一下。

我准备把 has_many 的东西嵌入到文档里面试试。

从我的应用来说,直接 cach 整页,是比较合理的。

#10 楼 @lukefan 所以你不就遇到了查询效率问题了吗。

<% cache @todolist do %> <!-- level 1 -->
  <% @todolist.todos.each do |todo| %>
    <% cache todo do %> <!-- level 2 -->
      <div class="todo">
        <b><%= todo.user.name %></b>
        <%= todo.content %>
      </div>
    <% end %>
  <% end %>
<% end %>

我把主从结构,改成了嵌入文档。效率就上去了。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号