写点什么

提高 Ruby on Rails 性能的几种技巧

  • 2010-08-18
  • 本文字数:1332 字

    阅读完需:约 4 分钟

Ruby on Rails 以其高度的易用性和灵活性著称,不过这些优点的背后还存在着性能的隐患。最近,资深 Ruby on Rails 作家 David Berube 提供了几个 Ruby on Rails 性能优化的技巧,对相关开发人员具有一定的借鉴意义。

David Berube 在文章中首先分析了 Rails 应用运行缓慢的原因:

  • Rails 总是会做一些假设为您加速开发。通常,这种假设是正确而有帮助的。不过,它们并不总能有益于性能,并且还会导致资源使用的效率低下——尤其是数据库资源。
  • 另一个显著的挑战是 N+1 问题…这会导致很多小查询的执行,而不是一个单一的大查询。例如,ActiveRecord 无从知道一组父记录中的哪一个会请求一个子记录,所以它会为每个父记录生成一个子记录查询。由于每查询的负荷,这种行为将导致明显的性能问题。
  • 由于 ActiveRecord 能够让如此众多的任务变得轻而易举,Rails 开发人员常常会形成 “SQL 不怎样” 的一种态度,即便在更适合使用 SQL 的时候,也会避免 SQL。创建和处理数量巨大的 ActiveRecord 对象的速度会非常缓慢,所以在有些情况下,直接编写一个无需实例化任何对象的 SQL 查询会更快些。

对于如何检测性能问题, David Berube 提供了一些建议:

  • 最好的工具之一是 Rails 开发日志,它通常位于每个开发机器上的 log/development.log 文件内。它具有各种综合指标:响应请求所花费的总时间、花费在数据库内的时间所占的百分比、生成视图所花时间的百分比等。
  • 在生产期间,通过查看 mysql_slow_log 可以找到很多有价值的信息。
  • 其中一个最强大也是最为有用的工具是 query_reviewer 插件。这个插件可显示在页面上有多少查询在执行以及页面生成需要多长时间。并且它还会自动分析 ActiveRecord 生成的 SQL 代码以便发现潜在问题。例如,它能找到不使用 MySQL 索引的查询,所以如果您忘记了索引一个重要的列并由此造成了性能问题,那么您将能很容易地找到这个列。此插件在一个弹出的
    (只在开发模式下可见)中显示了所有这类信息。

针对 N+1 查询问题,David Berube 举了一个未优化的代码示例:

<%@posts = Post.all(@posts).each do |p|%>

<%=p.category.name%>

<%=p.body%>

<%end%>

David Berube 指出,上述代码生成了一个查询外加 @posts 内的每行一个查询。由于每查询的负荷,这可能会成为一个很大的挑战。罪魁祸首是对 p.category.name 的调用。这个调用只应用于该特定的 post 对象,而不是整个 @posts 数组。这种情况通过使用立即加载可以修复。立即加载(Eager loading)意味着 Rails 将自动执行所需的查询来加载任何特定子对象的对象。Rails 将使用一个 JOIN SQL 语句或一个执行多个查询的策略。不过,假设指定了将要使用的所有子对象,那么将永远不会导致 N+1 的情形,在 N+1 情形下,一个循环的每个迭代都会生成额外的一个查询。优化后的代码如下:

<%@posts = Post.find(:all, :include=>[:category] @posts.each do |p|%>

<%=p.category.name%>

<%=p.body%>

<%end%>

比较复杂的情况包括嵌套的立即加载间接的立即加载

除了解决 N+1 问题之外,David Berube 还提供了其他一些优化建议:

InfoQ 将继续关注 Ruby on Rails 的发展,读者朋友可以通过 InfoQ 中文站 Ruby 社区了解更多信息。

2010-08-18 23:563701
用户头像

发布了 501 篇内容, 共 277.8 次阅读, 收获喜欢 63 次。

关注

评论

发布
暂无评论
发现更多内容

.NET CORE 对象池简述

喵叔

7月日更

【Flutter 专题】98 易忽略的【小而巧】的技术点汇总 (六)

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 7月日更

话题讨论|你知道集群、分布式、微服务区别吗?

Emotion

分布式 微服务 话题讨论 集群 话题王者

【LeetCode】雪糕的最大数量Java题解

Albert

算法 LeetCode 7月日更

2021最新一线大厂Java高级架构师面试题总结,上线3天获22w浏览量

Java 编程 程序员 架构 面试

Rust从0到1-Cargo-自定义构建

rust build cargo 构建

Ant蚂蚁挖矿系统软件开发资料

数据结构——树和二叉树

若尘

数据结构 二叉树

Java入门到架构-优秀书籍

Java入门到架构

Java 架构 入门 书籍

ES6中扩展运算符的8种用法

devpoint

数组去重 ES6 扩展运算符

对象存储手把手教一 | 用户数据访问控制管理ACL

QingStor分布式存储

云原生 对象存储 分布式存储

阿里+头条+抖音+百度+蚂蚁+京东面经,都是精髓!

欢喜学安卓

android 程序员 面试 移动开发

阿里+头条+腾讯等大厂Android面试题分享,神操作!

欢喜学安卓

android 程序员 面试 移动开发

「项目管理100问」之一篇优秀的周报是怎样炼成的?

万事ONES

项目 周报 ONES

架构思考

zk

微信 架构 微信业务架构

“Windows 找不到文件...”,怎么处理?

Emotion

windows 系统 找不到系统文件 windows找不到文件

李某逆道而行闭关三月,直接四杀斩获阿里/腾讯/京东/百度等大厂offer

Java架构师迁哥

极客时间-排位赛可视化工具

IT蜗壳-Tango

7月日更

PowerShell 数组

耳东@Erdong

PowerShell 7月日更

08 | 指针系列(二):记住,指针变量也是变量

Nydia

Go 学习笔记之 命名

架构精进之路

Go 语言 7月日更

推荐系统提供web服务的2种方式(二十四)

Databri_AI

算法 推荐系统 web服务

网络攻防学习笔记 Day61

穿过生命散发芬芳

网络攻防 7月日更

流量为王时代的短视频平台如何确保内容质量?|【话题讨论】

老猿Python

技术 内容审核 流量为王 负能量

多项目并行,项目经理如何有效管理项目进度?

万事ONES

研发管理工具 ONES 项目经理 项目管理工具

云原生领域的一些技术展望

名白

容器 云原生 Service Mesh service

“懂行人”合力共建“强富美高”数字经济助力千载金陵的数字一跃

脑极体

Linux之tail命令

入门小站

Linux

在线HTML实体转字符串工具

入门小站

工具

(VMware)ubuntu 环境下搭建 docker 镜像私服

逸少

Docker 镜像仓库

Redisson 分布式锁源码 01:可重入锁加锁

程序员小航

Java redis 源码 分布式锁 redisson

提高Ruby on Rails性能的几种技巧_Ruby_崔康_InfoQ精选文章