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

Rails where.not非空查询导致生产环境AJAX请求极慢问题求助

问题核心原因
  • 优先排查模板渲染耗时:所有SQL执行都在毫秒级,说明查询本身没有性能问题,耗时基本集中在JS模板渲染阶段。常见场景是:videos.js.erb模板中调用了未通过includes预加载的关联字段(比如关联的关联数据、附件地址等),生产环境数据量远大于开发环境,触发大量N+1查询导致超时;也可能是模板中存在调用第三方服务、大量字符串/日期计算等耗时逻辑。
  • 其次排查分页参数异常:你提供的EXPLAIN是offset=0的第一页查询情况,如果AJAX请求是滚动加载的后续分页,page参数过大导致offset极高,即使有索引MySQL也需要跳过大量无效行才能拿到目标数据,offset越大性能越差。
  • 最后排查联合索引覆盖率不足:当前查询走的是index_messages_on_is_removed_and_created_at索引,需要扫描3470行后过滤掉91%不符合is_featured=1、is_approved=1、video_link IS NOT NULL条件的数据,索引没有覆盖所有查询条件,数据量上涨后性能会明显下降。
修复方案
  • 第一步先定位耗时节点:在生产环境代码中埋点打印日志,分别记录fetch_videos执行前后、模板渲染前后的时间戳,确认耗时集中在数据查询还是模板渲染阶段。
  • 如果是渲染耗时:
    • 检查videos.js.erb模板中使用的所有关联字段,把未预加载的关联补充到includes参数中,比如用到user.avatar就改为includes(user: [:avatar])
    • 把模板中的复杂计算逻辑提前放到控制器完成,避免渲染过程中执行大量运算
    • 确认生产环境已经执行rails assets:precompile,避免资源路径计算导致的渲染阻塞
  • 如果是大offset分页慢:
    • 改用游标分页替代offset分页,AJAX请求时携带上一页最后一条数据的created_at值,查询条件改为where('created_at < ?', last_created_at),不需要offset即可快速定位到目标数据
  • 如果是索引效率问题:
    • 新增联合覆盖索引:add_index :messages, [:is_removed, :is_approved, :is_featured, :created_at], where: 'video_link IS NOT NULL',该索引可以直接覆盖所有查询条件,不需要回表过滤数据,查询性能会提升数倍。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 22:24:10