【问题标题】:optimizing page load with has_many and scope使用 has_many 和 scope 优化页面加载
【发布时间】:2020-01-09 19:56:14
【问题描述】:

我是一位经验丰富的程序员,对 ruby​​/rails 和数据库比较陌生。我创建了一个用于注册课程的大型网站。我认为我很聪明地使用范围和 has_many 创建课程注册类别。从逻辑上讲,它很好地封装了信息,但是我的页面现在加载速度非常慢,并且尝试快速加载让我感到困惑。

我有 Course、Person、CourseRole(学生、教师等)和 CourseSignup 模型,其中包括每个模型(Course、Person、CourseRole)。一切顺利。最近,我在 CourseRole 中设置了范围来定义注册的类别(我一直在硬编码角色名称,并希望摆脱它)。然后,我在 Course 中为每个类别设置了 has_many 关系。所以,Course 本质上是has_many course_signups,并且有我的分类

has_many :student_signups, -> { CourseSignup.student }, class_name: 'CourseSignup', foreign_key: :course_id
has_many :teacher_signups, -> { CourseSignup.teacher }, class_name: 'CourseSignup', foreign_key: :course_id

等等。 (我有6个类别)。我有一个页面列出了所有课程和每门课程的所有注册。喜欢:

Dodge Ball:
info about course
Students:
names of students
Teachers:
names of teachers
etc.

此页面加载速度非常慢。我试图在查询中添加包含语句(基于 Bullet gem 的建议),但它实际上使它变慢了。这让我觉得我让这件事变得比我应该做的更复杂,但我不知道如何解决它。我想我应该重组我的模型。但我喜欢 scopes/has_many 的抽象

页面是通过循环渲染显示一门课程的部分生成的。

@courses = @cuco_session.assigned_courses.includes(:period).order('periods.start_time')

有效,但速度很慢。

@courses = @cuco_session.assigned_courses
.includes(course_signups: [:person, :course_role])
.includes([:courses_rooms, :rooms])
.includes([:helper_signups, :student_signups, :volunteer_signups, :waiting_list_signups, :person_in_room_signups])
.includes(:period).order('periods.start_time')

同样有效,但速度更慢。

【问题讨论】:

  • 什么是periods?您没有在描述中命名该关联,您的表上有索引吗? @cuco_session 是什么? assigned_courses 是做什么的?也许子弹的日志和您视图的一些代码 sn-p 可以提供帮助。
  • 您需要提供更多信息才能获得更好的帮助 - 不清楚为什么在第二个查询示例中需要这么多表。每次执行包含时,您都在加入一个表,而表连接很昂贵。您想限制为此页面加载的表格数量。我不会有一个完整的“CourseRole”对象,除非它真的比单个字符串列有更多的信息。您应该查看 CourseSignup 的单表继承,其中“老师”和“学生”只是“类型”列中的不同值。这看起来应该只是@course.course_signups

标签: ruby-on-rails ruby scope include has-many


【解决方案1】:

*has_many :student_signups, -> { CourseSignup.student }, class_name: 'CourseSignup', foreign_key: :course_id

has_many :teacher_signups, -> { CourseSignup.teacher }, class_name: 'CourseSignup', foreign_key: :course_id*

以上代码可以使用单表继承重构

# app/models/person.rb
class Person < ApplicationRecord    
  #your code    
end

# app/models/teacher.rb
class Teacher < Person  
  #your code    
end

# app/models/student.rb
class Student < Person    
  #your code    
end

对于课程角色,您可以有一个单独的角色主表,并将人员表和角色表的引用放在课程角色表中

我希望上述解决方案能对您的问题有所了解。

【讨论】:

    【解决方案2】:

    我们需要有关视图中实际发生的情况的更多信息,才能真正回答您的页面速度慢的原因。

    还需要显示实际 SQL 的日志的 sn-p。

    您提到刚开始使用 Rails 在线使用数据库。如果不深入了解其中一些模型的结构,很难给出建议,但您是否考虑过仅用 Course 和 Person 之间的连接表替换 CourseSignup?看起来这就是你在这里得到的,但很难说。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多