【发布时间】:2015-01-12 08:21:25
【问题描述】:
在我的控制器操作中,我included 视图所需的所有关联,以避免多次调用数据库。 (我试图隔离视图层以仅呈现控制器收集的数据)。
我发现视图仍然与数据库通信(17 个查询):
这些 17 extra queries 不是必需的。由于我已经从控制台测试了控制器查询,并且它成功收集了部分 _dropdown(在 5 个查询 中)所需的所有数据,而无需任何进一步的数据库通信。
这是我的控制器中的query,它意味着避免N+1的问题。 (包括视图中调用的所有变量)
这里是下拉代码:
- @messages.each do |message|
%li.conversation-container
%a{href: conversation_path(message.conversation_id)}
- if message.sender != current_user
.notification-avatar{style: "background: url(#{message.sender.avatar_url}); background-size: contain; background-repeat: no-repeat; background-position: 50% 50%;"}
- else
- other_participant = message.conversation.conversation_participants.select{|p| p.user_id != current_user.id }.first.user
.notification-avatar{style: "background: url(#{other_participant.avatar_url}); background-size: contain; background-repeat: no-repeat; background-position: 50% 50%;"}
%p
%strong
- if message.sender != current_user
= message.sender.name
- else
= other_participant.name
%br
- if message.sender == current_user
%i.fa.fa-mail-reply-all
= truncate(message.body,length: 25)
.time
= time_ago_in_words(message.created_at)
ago
- if @messages.count == 0
%li
.empty-state-text-white
No messages
控制台输出:
2.0.0-p353 :006 > ms = Message.dropdown_for(3).all
Message Load (1.2ms) SELECT "messages".* FROM "messages" LEFT JOIN messages AS m ON messages.id != m.id
AND m.conversation_id = messages.conversation_id
AND messages.created_at < m.created_at INNER JOIN conversation_participants AS cp ON cp.conversation_id = messages.conversation_id AND cp.user_id = 3 WHERE (m.id IS NULL) ORDER BY cp.seen , cp.updated_at DESC LIMIT 5
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (6, 4, 5)
Conversation Load (0.4ms) SELECT "conversations".* FROM "conversations" WHERE "conversations"."id" IN (4, 2, 3)
ConversationParticipant Load (0.2ms) SELECT "conversation_participants".* FROM "conversation_participants" WHERE "conversation_participants"."conversation_id" IN (4, 2, 3)
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (6, 3, 4, 5)
=> [#<Message id: 8, body: "saSasa", sender_id: 6, conversation_id: 4, sent: true, attachment_id: nil, attachment_type: nil, created_at: "2014-11-17 16:05:40", updated_at: "2014-11-17 16:05:40">, #<Message id: 2, body: "asdnas dagsdashjdg jahs d", sender_id: 4, conversation_id: 2, sent: true, attachment_id: nil, attachment_type: nil, created_at: "2014-11-17 11:32:36", updated_at: "2014-11-17 11:32:36">, #<Message id: 6, body: "SADASD A DSA ", sender_id: 5, conversation_id: 3, sent: true, attachment_id: nil, attachment_type: nil, created_at: "2014-11-17 13:43:34", updated_at: "2014-11-17 13:43:34">]
2.0.0-p353 :007 > ms.first.conversation.conversation_participants.select{|cp| cp.user_id != 3}.first.user
=> #<User id: 6, first_name: "Ddsfsd", middle_name: nil, last_name: "Fsdfsd", photo: nil, email: "1@k.com", encrypted_password: "$2a$10$5sGIb2DbQ1ctMrTzD3AJ0uV18hhiC5Ei1wcfE7MSAvRU...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 1, current_sign_in_at: "2014-11-17 15:27:06", last_sign_in_at: "2014-11-17 15:27:06", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", confirmation_token: nil, confirmed_at: "2014-11-17 15:27:48", confirmation_sent_at: "2014-11-17 15:27:05", unconfirmed_email: nil, failed_attempts: 0, unlock_token: nil, locked_at: nil, authentication_token: nil, created_at: "2014-11-17 15:27:05", updated_at: "2014-11-17 15:27:48", slug: "ddsfsd_fsdfsd">
2.0.0-p353 :008 > ms.count
=> 3
如何阻止这些查询无目的运行?
【问题讨论】:
-
实际上我已经尝试断开与控制台的连接,一切都按预期工作,但是当我从服务器将它添加到我的控制器(访问相同的属性)时出现错误
-
能否请您发布您的索引和下拉视图文件以及对话控制器索引操作的代码?
-
Rails 范围可让您构建查询并在使用它们时执行。要执行,您可以调用 .all、.count、.each 或 .first。您是否尝试在控制器操作中将
.all添加到查询的末尾? -
是的,我也是,
to_a。事情是预加载似乎比它应该采取更多的查询。 -
从日志中,您能否粘贴您想要消除/认为不需要的 17 个查询?如果它们几乎相同,您可以只粘贴其中一个查询。
标签: ruby-on-rails ruby-on-rails-3 performance eager-loading preloading