在Ruby on Rails应用程序中使用MySQL视图来提高性能

时间:2009-02-09 21:40:08

标签: mysql ruby-on-rails ruby performance

我在rails项目中遇到了一些性能问题(在rails 2.0.5上运行),例如在我的用户管理页面中。

我的用户模型有很多关系(细节,地址,角色......),他们加载了急切的加载。这会产生非常大的SQL查询,在某些情况下,加载30个用户需要将近一分钟。另一方面,删除急切加载会产生数百个查询,最后我遇到了同样的问题:加载页面很慢。

我曾经在Java& amp; Oracle,对于我用来创建视图的这种大查询,这些视图然后被缓存以便更快地呈现。维护非常无聊,因为我必须在视图脚本等中手动更新数据库字段......

但它真的有很棒的表现....所以我想知道是否有人试图在活动记录中实现某些东西以利用Mysql视图?

我刚做了一些基本测试,这是我的观点(这个例子只有几个字段,我有一个标准的Res​​tful Authentication用户表,以及一个用于个人数据的大表“详细信息”):

CREATE VIEW users_vs AS SELECT
users.id              ,          
users.login           ,          
users.email           ,          
details.last_name           ,
details.first_name          ,
details.phone               ,
details.fax                 ,
FROM `users`   LEFT OUTER JOIN `details` ON details.user_id = users.id ;

然后是模特:

class UsersV < ActiveRecord::Base
end

在我的控制台中尝试了一些事情:

u=UsersV.find(:first)  # ok !
u=UsersV.find_by_last_name('smith') #=> ok !
us=UsersV.find_all_by_last_name('smith') #=> ok too !

查看日志,简单查询的处理方式与任何表查询相同

当然,这些假模型只会用于读取数据。

我想知道:

  • 如果有人已经尝试过了吗?

  • 如果这是个好主意?

  • 如果我应该查看类似memcached的内容......

4 个答案:

答案 0 :(得分:5)

视图的“问题”(在这种情况下,你可能想要一个物化视图,假设复杂查询所基于的数据不会经常改变)就是你违反了Rails'DRY',在某种程度上(为视图添加了UserV模型,纯粹主义者会争辩说这是用户模型的重复。)

因此,理想的解决方案是从复杂查询的RDBMS中获得最大收益。如果未缓存的查询仍然需要很长时间才能执行(你仍然必须运行它们来填充memcached),或者如果你不能容纳一点时间 - 软糖(即缓存的结果,那么)memcached将无法帮助你必须是实时精确的)和/或所涉及的表经常被修改。

  • 在MySQL中看看你是否可以进一步优化查询,因此需要几毫秒而不是秒(添加适当的索引,运行ANALYZE 等)。
  • 如果您可以选择使用/尝试其他RDBMS,例如Postgres,请务必尝试一下。 与其他基于成本的引擎(如Oracle和Postgres)相比,MySQL在复杂连接(InnoDB)方面令人震惊。我从MySQL切换到Postgres,在MySQL上使用30s +的复杂连接(所有索引就位)在Postgres上花费了几毫秒。如果玩Postgres,请充分利用PGAdminIII的图形解释计划工具。

答案 1 :(得分:3)

我定期在Rails中使用表视图,我对它很满意。 Rails将它们视为普通表,只要您只使用它们来读取记录(这是我通常的情况)。只要您的视图只包含一个表,您甚至可以使用它来执行所有其他CRUD操作。所以,我的回答是:就这样做。

答案 2 :(得分:1)

http://github.com/aeden/rails_sql_views/tree/master

↑在迁移中创建视图。我也只会在极端情况下使用它们,因为它们会将逻辑隐藏在你的应用程序之外,这通常是不好的。

如果你有那么多关联数据,你可以使用DataMapper而不是ActiveRecord和Rails,因为它支持延迟加载数据。

答案 3 :(得分:1)

确保已启用MySQL Query Caching以缓存结果集。我有几种情况,即使你正在更多地访问服务器,许多没有连接的查询与几个带连接的查询实际上更快。