基于has_many through关联的学校教师数量优化查询求助
优化查询某所学校教师数量的方案
没问题,我来帮你搞定这个查询优化的事儿!首先得先确认你的模型关联是否正确,先把常见的has_many through关联写法列出来,方便你对照:
模型关联定义
# app/models/school.rb class School < ApplicationRecord has_many :school_teacher_subjects has_many :teachers, through: :school_teacher_subjects has_many :subjects, through: :school_teacher_subjects end # app/models/teacher.rb class Teacher < ApplicationRecord has_many :school_teacher_subjects has_many :schools, through: :school_teacher_subjects has_many :subjects, through: :school_teacher_subjects end # app/models/subject.rb class Subject < ApplicationRecord has_many :school_teacher_subjects has_many :schools, through: :school_teacher_subjects has_many :teachers, through: :school_teacher_subjects end # 关联表school_teacher_subjects的迁移参考 # create_table :school_teacher_subjects do |t| # t.references :school, null: false, foreign_key: true # t.references :teacher, null: false, foreign_key: true # t.references :subject, null: false, foreign_key: true # t.timestamps # end
优化查询方案
1. 直接数据库层面统计(性能最优)
这种方式不需要加载任何Teacher实例,直接在数据库完成计数和去重,是效率最高的写法:
# 通过学校名称查询教师数量 school_teacher_count = School.joins(:teachers) .where(name: "你的目标学校名称") .distinct .count(:teacher_id) # 如果需要结合城市筛选 school_teacher_count = School.joins(:teachers) .where(city: "目标城市", name: "学校名称") .distinct .count(:teacher_id)
这里用distinct是因为一个教师可能关联多个科目(在school_teacher_subjects中有多条记录),去重后才能得到真实的教师数量。
2. 已加载School实例时的优化查询
如果已经获取了School对象,比如通过find或find_by拿到了学校实例,那可以通过预加载避免N+1查询:
# 预加载teachers关联,避免后续查询触发N+1 school = School.includes(:teachers).find_by(name: "目标学校名称") # 去重后计数 teacher_count = school.teachers.distinct.count
额外性能优化:给关联表加索引
为了让数据库更快定位关联记录,建议给school_teacher_subjects表添加联合索引:
# 生成迁移文件后执行 add_index :school_teacher_subjects, [:school_id, :teacher_id], unique: false
这个索引会大幅提升joins和count操作的速度,尤其是数据量较大的时候。
内容的提问来源于stack exchange,提问作者Eduardorph
相关产品推荐
相关产品推荐

