写点什么

提高 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:563364
用户头像

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

关注

评论

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

不同公司产品经理岗位对比

LouisN

遇到代码缺陷不要慌,马上教你快速检测和修复

华为云开发者联盟

代码 bug 缺陷检测 代码缺陷

万字多图 | UML 入门指南

白色蜗牛

Java 程序员 后端 架构设计 UML

『CDN』让你的网站访问起来更加柔顺丝滑

古时的风筝

CDN

当音乐学博士搞起编程...

程序猿DD

Spring Frame

区块链十年与传统金融的变化

CECBC

区块链 金融

架构师训练营第十三周作业

李日盛

PageRank

即构小程序直播组件集成教程

ZEGO即构

为什么我认为 Deno 是一个迈向错误方向的 JavaScript 运行时?

hylerrix

typescript rust nodejs deno V8

矿机挖矿APP系统模式开发平台

v16629866266

面试官:你真的了解Redis分布式锁吗?

鄙人薛某

redis 分布式锁 线程安全 RedLock

一文解析DDD中台和微服务设计

欧创新

中台 微服务 领域驱动设计 DDD

用AI「驯服」人类幼崽,手头有娃的可以试试

博文视点Broadview

人工智能 联邦学习 强化学习 集成学习 技术宅

区块链科普系列:区块链是什么?

CECBC

区块链

「产品经理训练营」第一章作业

Sòrγy_じò ぴé

产品经理训练营

Kubernetes概念篇:基本概念和术语

xcbeyond

Kubernetes 容器 pod 28天写作 Kubernetes从入门到精通

来不及解释!Linux常用命令大全,先收藏再说

华为云开发者联盟

Linux 编程 命令行 命令

架构师训练营W13作业

Geek_f06ede

关心群众生活,注意工作方法 Jan 15, 2021

王泰

28天写作

同事试用期没过就被劝退,我比他还难受

熊斌

职场 成长笔记 28天写作 职场新人

自动量化搬砖套利交易机器人系统软件APP开发

系统开发

一文带你探究Sentinel的独特初始化

华为云开发者联盟

redis sentinel 框架

第十三周课后练习

晴空万里

架构师训练营第2期

古有诸葛亮八卦阵阻敌,今有iptables护网安

华为云开发者联盟

安全 防火墙 网络 iptables 数据包

“反垄断”来袭,对产业区块链有什么启发

CECBC

市场垄断

特斯拉自建ERP的背后

明道云

DevSecOps安全检查清单

啸天

安全 DevSecOps 应用安全

Volcano架构设计与原理介绍

华为云原生团队

大数据 AI 云原生 高性能 批量计算

解决div里面img图片下方有空白的问题

德育处主任

CSS html html5 大前端 28天写作

生产者与消费者模式,数组阻塞队列(ArrayBlockingQueue)

码农架构

Java 学习 架构 并发编程

敏捷里为何倡导固定迭代周期?

万事ONES

敏捷开发 研发管理 迭代

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