重庆大型网站建设,wordpress 美食,wordpress移动端底部导航,王野天简历rack-mini-profiler 这个 gem,可以永远显示网页的加载时间。#xff08;2300✨#xff09;开发环境和产品环境都可以用。#xff08;生成非常详细的报告#xff09; development环境,直接使用gem rack-mini-profilerproduction环境#xff0c;1. gem rack-mini-profiler,…rack-mini-profiler 这个 gem,可以永远显示网页的加载时间。2300✨开发环境和产品环境都可以用。生成非常详细的报告 development环境,直接使用gem rack-mini-profilerproduction环境1. gem rack-mini-profiler, require: false 让2. 然后运行bundle exec rails g rack_profiler:install 这样在开发环境下也可以使用。 以下服务可以收集网站实际营运的数据找出哪些部分是效能不好的地方加以改善 New RelicSkylightScout后端效能提速的方向 对后端来说一个方向是提供 Rails 和 Ruby 代码的效能一个方向是提供数据库方面的效能。 主要是query查询SQL的效能提升空间大。 1. 避免N 1的query includes()让你存取Post模型的关联对象user的属性却不会产生额外的查询语句。用于简单的join的执行速度的改进。 可以嵌套可以指定多个关系可以附加where具体看API 对关联可以使用 def index posts Post.includes(:user).page(params[:page]) end SELECT posts.* FROM posts LIMIT ? [[LIMIT, 2]] SELECT users.* FROM users WHERE users.id IN (1, 5) def show post Post.find(params[:id]) comments post.comments.includes(:user) end 多个关联和加嵌套 def index posts Post.includes(:user, :liked_users, {:comments :user}).page(params[:page]) end {:comments :user}是因为post关联comments下一层comments关联了user。 td% post.comments.map{ |c| c.user.display_name }%/td 加上条件查询 可以在include()后面直接加上where()。 使用scope(name, body, block),预先设置查询的rails语法. 就是一个类方法。返回一个ActiveRecord::Relation。 可以把返回结果当array用Enumerable的方法。 scope可以连接scope或类方法。 例子 如果希望在index页面只显示公开的comments即comment的status属性的值是public,同时不希望产生N1query, 改MVC模型 则在Models/post.rb中添加 has_many :comments, - { where( status: public)}, class_name: Comment 在Controllers/posts_controller.rb中的index方法中修改 {:comment :user}改为{:visible_comment :user} 在views/posts/index.html.erb中修改 post.comments为post.visble_comments Bullet在开发时协助侦测 N1 queries gem https://github.com/flyerhzm/bullet 5500✨ 注意在配置时注释掉不需要的gem的功能。然后打开页面如果遇到N1 query就会弹出窗口。 Rails.application.configure do config.after_initialize do Bullet.enable true Bullet.alert true #弹出提示框。 Bullet.bullet_logger true Bullet.console true Bullet.rails_logger true #在terminal显示提升 Bullet.add_footer true #在当前页角显示提升 end end activerecord内存的优化 1.不要用all,可以使用分页的gem。 will_paginate 或 kaminari 2. 真要捞全部数据使用批处理方法 find_each find_in_batches。 例子 在数据库内新增一个字段并赋值。 db/migrate/2017XXXXXXXXXX_add_date_to_posts.rb class AddDateToPosts ActiveRecord::Migration[5.1]def changeadd_column :posts, :date, :datePost.find_each do |post|post.date post.created_at.to_datepost.save( :validate false )endendend 3. Preload技术使用复杂的语法糖复杂的Sql一次性从数据库捞出所有想要的数据存入了内存。 对不同的需求使用不同的调用方法从内存中获取记录。 def show post Post.find(params[:id]) if current_user all_comments post.comments.where(status ? OR (status ? AND user_id ?),public, private, current_user.id).includes(:user) comments all_comments.select{ |x| x.status public } my_comments all_comments.select{ |x| x.status private } else comments post.comments.visible.includes(:user) end end 对应的查询语法 SELECT comments.* FROM comments WHERE comments.post_id ? AND (status private OR (status public AND user_id 1)) [[post_id, 1]] 4. count和size: size可以返回已经加载的collection的数量如果没有加载则调用count的sql方法。所以在collection中都用size 总结sql优化是优化已经实现的功能。不可能有先见之明。 5. pluck()选择字段在只需要记录的部分字段的情况下使用的。可以节省内存。直接返回一个数组。 Post.all.map{|x| x.id } 是先捞出输出生成ActiveRecord然后再生成数组 Post.pluck(:id)直接捞需要的数据生成数组不会生成ActiveRecord。 pluck()和select()用有区别select()有2个用法 1。select()返回的是activerecord对象集合。 ⚠️比较好的写法是: Post.select(:id, :column_name, ...)这样会带上id。否则返回的activerecord对象不带id索引. 2。select{|x| 条件 } 这是另一种用法返回数组对象集合。 数据库的sql优化 使用复杂的sql语法进行如报表之类的计算。因为在数据库中的计算比调出数据再用Ruby计算的速度快很多。 因此, 如COUNT, MAX, MIN, SUM, AVG等都直接用数据库计算比较好。 对应的Rails语法糖count(), maximum(), minimum(), sum(), average(). 例子 SQL: SELECT posts.*, COUNT(subscriptions.id) as subscriptions_count FROM posts INNER JOIN subscriptions ON subscriptions.post_id posts.id GROUP BY posts.id Rails语法糖 Post.joins(:subscriptions).group(posts.id).select(posts.*, count(subscriptions.id) as subscriptions_count) group()和select()可以换顺序不影响SQL。 解释group by 用于集合计算的函数并分组显示结果。 使用计数缓存counter_cache 比如以前没有使用counter_cache现在已经有了一堆相关的记录。可以 1. rails g migration AddXxxToXxxs xxx:type然后在db/migrate/XXX_add_xxx中添加 2. add_column :users, :posts_count, :integer, default: 0, null: false User.pluck(:id).each {|id| User.reset_counters(id, :posts)} ⚠️reset_counters(id, *counters, touch: nil) 3. 在posts.rb中加上 belongs_to :user, counter_cache: true 4. 在user的posts数量发生变化时可以更新它使用update_counters(id, counters, touch: nil) User.update_counters(user.id, posts_count: 1 ) ⚠️id, 想要更新一个counter的对象的id或者一数组ids ⚠️counters是hash, 要更新的字段的名字做key字段的值是value. ⚠️ 如果设置选项touchtrue代表更新时间戳updated_at。 Rails 内建的 Counter Cache 功能比较简单如果你需要更多功能请参考 https://github.com/magnusvk/counter_culture 这个 gem。 小结论什么时候用逆规范化做优化 如果不常显示该数据 可以用纯 SQL 的方式来解决。但是如果需要经常显示该数据就可以考虑用逆规范化的方式将数据缓存下来。这样效能可以更好。但是缺点就是需要维护该数据的正确性要写的 Ruby 代码也比较多。 考量读取的频率 v.s. 更新缓存数据的成本。 比如点赞数关注数。无需时时更新。可以用逆规范化。 改进render partial的效能比较小 % posts.each do |post| % % render partial: post, locals: {post: post}% % end % 改为用a collection of partials:% render partial: post, collection: posts, as: :post% 数据库索引 加快查询速度但会占内存 add_index(table_name, column_name, options{}) ,各种例子的用法见API 以下需要加上index: 外部键(Foreign key)会被排序的字段(被放在order方法中)会被查询的字段(被放在where方法中)会被group的字段(被放在group方法中)order(id desc)等同于created_at desc效能更好。这是因为id是integer格式而created_at是datetime格式。因此⚠️index对不同的数据格式的效率也不同。效率上Boolean integer String Date Datetime 内存缓存 超高流量的网站会需要用到缓存来进一步提升后端效能。本教程没有提及如何做缓存有兴趣的同学请直接看老师的Rails 实战圣经。 Rails的各类内存缓存比如俄罗斯套娃机制可以看guide。博客里也有相应文章。 转载于:https://www.cnblogs.com/chentianwei/p/9398380.html