You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过为模型添加外键优化SQL查询及account_id空值问题解决

优化关联查询:给Sale表添加直接关联Account的字段并批量填充数据

问题背景

原本的关联结构是Account→User→Sale,查询Sale所属Account时需要经过两层关联,导致SQL查询变慢。为了优化性能,计划给Sale表直接添加account_id字段,替代通过User间接关联Account的方式。

执行初始迁移后,sales表确实新增了account_id字段,但所有记录的该字段值都是nil——原以为靠模型关联就能自动填充这个值,实际完全没生效。

初始迁移代码(这里还犯了个表名错误,写成了:bids而非:sales):

def change
  add_reference :bids, :account, type: :integer, after: :user_id, foreign_key: true
end

原模型关联关系:

User 模型

belongs_to :account
has_many :sales

Account 模型

has_many :users, dependent: :destroy
has_many :sales, through: :users

Sale 模型

belongs_to :user
has_one :account, through: :user

创建Sale的代码流程:

sale = Sale.new(company: item.company, sale_type: params[:sale_type])
# 中间用户校验逻辑...
sale = item.place_sale!(user, params[:sale_type], params[:amount], params[:note], nil, params[:custom_amount].present?)

最终解决步骤

1. 修正迁移脚本,批量填充历史数据

新迁移脚本不仅正确添加sales表的account_id字段,还通过原生SQL批量更新已有数据,把User关联的Account ID同步到Sale记录里:

def change
  add_reference :sales, :account, type: :integer, after: :user_id, foreign_key: {on_delete: :nullify}, index: true
  reversible do |dir|
    dir.up do
      ActiveRecord::Base.connection.execute("UPDATE sales JOIN users ON sales.user_id = users.id SET sales.account_id = users.account_id;")
    end
  end
end

这里做了几个关键调整:

  • 修正了初始迁移的表名错误,把:bids改为:sales
  • 给account_id添加索引,提升后续查询性能
  • 外键设置on_delete: :nullify,避免Account被删除时连带删除关联的Sale

2. 更新模型关联关系

移除原来的间接关联,改成Sale与Account直接关联:

修改后的 Sale 模型

belongs_to :user
belongs_to :account # 新增直接关联

修改后的 Account 模型

has_many :users, dependent: :destroy
has_many :sales # 移除through: :users,改为直接关联

3. 确保新创建的Sale自动填充account_id

为了避免新创建的Sale再出现account_id为nil的情况,可以在创建逻辑里手动赋值,或者给Sale模型加回调:

  • 方式一:在place_sale!方法内部赋值
# 在place_sale!创建Sale的逻辑中
sale.account_id = user.account_id
  • 方式二:给Sale模型添加回调
class Sale < ApplicationRecord
  belongs_to :user
  belongs_to :account

  before_save :set_account_id_from_user

  private

  def set_account_id_from_user
    self.account_id ||= user&.account_id
  end
end

内容的提问来源于stack exchange,提问作者slime_saw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 03:20:25