简体   繁体   English

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

[英]Using MySQL views in a Ruby on Rails app to improve performance

I'm having some performance issues in a rails project (running on rails 2.0.5), for example in my user administration pages. 我在rails项目中遇到了一些性能问题(在rails 2.0.5上运行),例如在我的用户管理页面中。

my user model has many relations (details, addresses, roles...) who get loaded with eager loading. 我的用户模型有很多关系(细节,地址,角色...),他们加载了急切的加载。 That creates really huge SQL queries, for some cases, it takes almost a minute to load 30 users. 这会产生非常大的SQL查询,在某些情况下,加载30个用户需要将近一分钟。 On the other hand removing the eager loading generates hundreds of queries, in the end I have the same problem: loading the page is slow. 另一方面,删除急切加载会产生数百个查询,最后我遇到了同样的问题:加载页面速度很慢。

I used to develop on Java & Oracle, for this kind of big queries I used to create views, those views were then cached for a faster rendering. 我曾经在Java和Oracle上进行开发,对于我用于创建视图的这种大查询,这些视图随后被缓存以便更快地呈现。 It was extremely boring to maintain, as I had to update the database fields manually in the views scripts etc... 维护非常无聊,因为我必须在视图脚本中手动更新数据库字段等...

BUT it really had fantastic performances.... so I was wondering if anyone ever tried to implement something to take benefits of Mysql views in active record ? 但它真的有很棒的表现....所以我想知道是否有人试图在活动记录中实现某些东西以利用Mysql视图?

I just did some basic tests, here's my view (just a few fields for the example, I have a standard Restful Authentication user table, and a big table "details" for the personal datas ): 我刚做了一些基本的测试,这是我的观点(这个例子只有几个字段,我有一个标准的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 ;

Then a model: 然后一个模型:

class UsersV < ActiveRecord::Base
end

Tried a few things in my console: 在我的控制台中尝试了一些事情:

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

looking at the log, simple queries are just handled the same way as any table queries 查看日志,简单查询的处理方式与任何表查询相同

Of course, those fake models would just be used to read datas. 当然,那些假模型只会用于读取数据。

I'm wondering: 我在想:

  • if someone already tried that ? 如果有人已经尝试过吗?

  • if it's a good idea ? 如果这是个好主意?

  • if I should look into something like memcached instead... 如果我应该调查类似memcached的东西......

The "problem" with views (and in this case you'd probably want a materialized view, assuming the data on which the complex query is based doesn't change often) is that you violate Rails' DRY'ness, to some extent (the addition of the UserV model for the view, which the purists will argue is a duplication of the User model.) 视图的“问题”(在这种情况下,您可能想要一个物化视图,假设复杂查询所基于的数据不会经常更改)是您在某种程度上违反了Rails的DRY'(为视图添加了UserV模型,纯粹主义者认为这是用户模型的重复。)

So the ideal solution would be to get the most out of the RDBMS for your complex query. 因此,理想的解决方案是为您的复杂查询充分利用RDBMS。 Memcached will not be able to help you if the uncached queries still take a long time to execute (you still have to run them to populate memcached), or if you can't accommodate a bit of time-fudge (ie cached results don't have to be realtime-exact) and/or the tables involved get modified often. 如果未缓存的查询仍然需要很长时间才能执行(你仍然必须运行它们来填充memcached),或者如果你不能容纳一点时间 - 软糖(即缓存的结果,那么Memcached将无法帮助你)必须是实时精确的)和/或所涉及的表经常被修改。

  • In MySQL see if you can optimize the query further so it would take milliseconds instead of seconds ( add appropriate indices, run ANALYZE , etc.) 在MySQL中,看看你是否可以进一步优化查询,因此需要几毫秒而不是秒( 添加适当的索引,运行ANALYZE等)
  • If you have the option of using/trying out another RDBMS such as Postgres, by all means give it a try. 如果您可以选择使用/尝试其他RDBMS,例如Postgres,请务必尝试一下。 MySQL is appallingly bad with complex joins (InnoDB) when compared with other cost-based engines like Oracle and Postgres. 与其他基于成本的引擎(如Oracle和Postgres)相比, MySQL在复杂连接 (InnoDB)方面令人震惊 I switched from MySQL to Postgres and complex joins that would take 30s+ on MySQL (with all indices in place) take milliseconds on Postgres. 我从MySQL切换到Postgres,在MySQL上使用30s +的复杂连接(所有索引就位)在Postgres上花费了几毫秒。 If playing with Postgres make good use of PGAdminIII's graphical explain plan tool. 如果玩Postgres可以很好地利用PGAdminIII的图形解释计划工具。

I use table views in Rails on a regular basis and I'm pretty happy about it. 我定期在Rails中使用表视图,我很高兴。 Rails treat them as normal tables as far as you only use them to read the records (which is my usual scenario). Rails将它们视为普通表,只要您只使用它们来读取记录(这是我通常的情况)。 As long as your view consists only of one table, you can even do all the other CRUD stuff with it, too. 只要您的视图只包含一个表,您甚至可以使用它来执行所有其他CRUD操作。 So, my answer is: just do it. 所以,我的答案是:做到这一点。

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

↑ To create the view in a migration. ↑在迁移中创建视图。 I would also only use them in extreme cases as they hide logic away from your application and that is generally not good. 我也只会在极端情况下使用它们,因为它们会将逻辑隐藏在您的应用程序之外,这通常是不好的。

If you have that much associated data you could look at using something like DataMapper instead of ActiveRecord with Rails as it supports lazy-loading data as required. 如果你有那么多关联的数据,你可以使用DataMapper而不是ActiveRecord和Rails,因为它支持延迟加载数据。

Ensure that the MySQL Query Caching is enabled which caches the result set. 确保启用了MySQL Query Caching ,缓存结果集。 I've had several situations where many queries without joins versus few queries with joins is actually faster even though you're making more trips to the server. 我有几种情况,即使你正在更多地访问服务器,许多没有连接的查询与几个带连接的查询实际上更快。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM