我有一个表格,它在 3 周内(总共 504 个 1 小时时隙)接受一天中每个小时的真/假值。
我正在尝试减少加载此页面所需的时间(目前在本地为 3 秒,但在 heroku 上为 15 秒;是网站上任何其他页面时间的两倍多)。
编码
表格如下所示:
<% 504.times do |i| %>
<% availability = @physician.availabilities.find { |a| a.time_slot == @current_hour + (i + 1)*3600 } %>
<% availability ||= @physician.availabilities.build(time_slot: all_one_hour_slots[i] ) %>
# Form etc
少量i
会很好,但因为它发生了 504 次,所以它很慢。
当我查看服务器日志时,它出现了一个 n+1 问题(我认为这可能是由 引起的@physician.availabilities.find
)。但我不确定在保持功能的同时是否可以成功避免这种情况。
问题
如何在保留功能的同时加快页面加载速度?
其他注意事项
- 网站上的每个页面都在 7 秒内加载,所以这个页面是 15 秒是很成问题的。
- heroku dyno 是standard, heroku postgres 数据库是hobby-basic。
- 我愿意使用任何最好的方法来减少时间。例如,如果可以进行代码优化,那就太好了。但是,如果将 postgres 数据库从 hobby-basic 增加到 standard-0 会有所帮助,我也会考虑这一点。
- 日志样本(这是 6 行几乎相同,但总共有 504 行这样的!):
CACHE (0.0ms) SELECT "appointments"."start_time" FROM "appointments" WHERE "appointments"."physician_id" = $1 [["physician_id", 10]]
↳ app/views/physicians/_form.html.erb:37
CACHE (0.0ms) SELECT "appointments"."start_time" FROM "appointments" WHERE "appointments"."physician_id" = $1 [["physician_id", 10]]
↳ app/views/physicians/_form.html.erb:37
CACHE (0.0ms) SELECT "appointments"."start_time" FROM "appointments" WHERE "appointments"."physician_id" = $1 [["physician_id", 10]]
↳ app/views/physicians/_form.html.erb:37
CACHE (0.0ms) SELECT "appointments"."start_time" FROM "appointments" WHERE "appointments"."physician_id" = $1 [["physician_id", 10]]
↳ app/views/physicians/_form.html.erb:37
CACHE (0.0ms) SELECT "appointments"."start_time" FROM "appointments" WHERE "appointments"."physician_id" = $1 [["physician_id", 10]]
↳ app/views/physicians/_form.html.erb:37
CACHE (0.0ms) SELECT "appointments"."start_time" FROM "appointments" WHERE "appointments"."physician_id" = $1 [["physician_id", 10]]
↳ app/views/physicians/_form.html.erb:37
更长的解释
这是视图中的表单
<% 504.times do |i| %>
<% availability = @physician.availabilities.find { |a| a.time_slot == @current_hour + (i + 1)*3600 } %>
<% availability ||= @physician.availabilities.build(time_slot: all_one_hour_slots_from_one_hour_after_current_time[i] ) %>
<% if @appointments.pluck(:start_time).any? { |e| e == availability.time_slot } %>
<b><%= availability.time_slot.to_s + " Time slot booked" %></b>
<% else %><%# Line 37 %>
<%= form.fields_for :availabilities, availability do |availability_form| %>
<%= availability_form.hidden_field :time_slot, value: availability.time_slot %>
<%= availability_form.label :_destroy do %>
<%= availability_form.check_box :_destroy, {checked: availability.persisted?}, '0', '1' %>
<%= nice_datetime(availability.time_slot) %>
<% end %>
<% end %><%# end form.fields_for %>
<% end %><%# end booked vs available %>
<% end %><%# end 504 loop %>
这是控制器动作
# physicians controller
@physician = current_user.physician
@appointments = Physician.find(current_user.physician.id).appointments
@current_hour = Time.current.beginning_of_hour
一个快速的文字解释:基本上 504 循环只是循环通过 504 个 1 小时的时间段,如果该时间已经预订,则显示“时间段已预订”,或者如果时间段未预订,则显示复选框(因此医生可以决定是否让自己在那个时间段可用)。
最后,完整的日志在这里