201705 Ruby基础拾遗

  • Rails
    • 大数据情况下
    • 结论:当数据量大到一定程序,请尽量使用原生sql

      Mixin

      • Mixin include: 作为实例方法引入
      • extend : 作为类方法引入
      • Inheritance(继承)

      override

      ruby class內的method都是可以被修改、添加定义的。
      修改影响所有实例,包括修改操作前创建的实例。

      异常处理

      begin
        # 可能會發生例外的 code
      rescue AExceptionClass => some_variable
        # 屬於 AExceptionClass 的例外發生時 run 這段 code
      rescue BExceptionClass => some_other_variable
        # 屬於 BExceptionClass 的例外發生時 run 這段 code
      else
        # 都沒有例外發生時 run 這段 code
      ensure
        # 無論有沒有發生例外,都會 run 這段 code
      end
      
      def foo
        # 正常時的處理
      rescue
        # 發生例外時的處理
      end
      

      super 与super()

      • super:呼叫父类别的同名函式,并且将本函式的所有参数传入父类别的同名函式。
      • super(): 带括号则表示呼叫父类别的同名函式,但是不传入任何参数

      使用%()处理需要string interpolation但同时也需要" "(double quote)的状况

      <%= "<div class=\"name\"> #{name} </div>" %>
      <%= "<div class='name'> #{name} </div>" %>
      <%= %(<div class="name">#{name}</div>) %>
      
      

      当要宣告一个拥有多字串的Array 阵列时,偏好使用%w

      array = ["A", "B", "C", "D"]
      
      array = %w(A B C D)
      

      Rails

      大数据情况下

      1. 尽量避免使用ActiveRecord Object

      ActiveRecor,rake task在大数据量下运行是非常慢的,应该直接使用sql语句进行数据操作

      2. 有 update_all 可以用,少用 for / each

      posts = Post.where(:board_id => 5)
      post.each do |post|
        post.board_id = 1
        post.save
      end
      当数据量达到十万条时,一天也跑不完
       
      Rails 提供了 update_all 可以用,相当于直接使用sql的效果
      Post.update_all({:board_id => 1}, {:board_id => 5})
      

      3.不要直接使用Post.all.each,可以用 find_in_batches

      如果十万笔数据加载到内存,估计超过10G,程序可能直接闪退

      Post.find_in_batches(:conditions => "board_id = 5", :batch_size => 1000) do |posts|
        posts.each do |post|
          post.board_id = 1
          post.save
        end
      end
      

      4. 批量修改数据记录时,使用transaction 跳过每次的 BEGIN COMMIT 过程

      Post.find_in_batches(:conditions => "board_id = 5", :batch_size => 1000) do |posts|
        Post.transaction do 
          posts.each do |post|
            post.board_id = 1
            post.save
          end
        end 
      end
      

      5.使用 update_column / sneacky-save 而非原生 save

      save 存储资料时,会调用一堆 validator 和 callbacks
      update_column / sneacky-save会跳过,直接修改数据库字段,区别是update_column一次只能修改一个字段,后者可修改多个字段。

      6.可以的话使用 Post.select("column 1, colum2").where("id < 10"), 代替Post.where("id < 10")

      7. 使用 delegate 把大字段搬出去,独立成表

      class Post < ActiveRecord::Base
        has_one :meta
         
        after_create :create_meta
        
        deleagte :content, :to => :meta
      end
      

      8. 添加索引INDEX,避免索引过长

      避免直接对varchar(255) 加索引
      ALTER TABLE post DROP INDEX PTitle, ADD INDEX(PTitle(13));

      9. delete / destroy的时间成本

      • destroy 刪除资料并callbacks
      • delete 刪除资料,不callbacks
      • destroy_all 和 delete_all 也类似

      Mysql提供TRUNCATE TABLE清空表
      delete_all不触发callback,但是会update index,所以相比TRUNCATE TABLE会很慢

      TRUNCATE TABLE
      ActiveRecord::Base.connection.execute("TRUNCATE TABLE #{table_name}")

      10. 无法避免的耗时操作丟到 background job 去操作。

      • delayed_job (不推荐)
      • resque
      • sidekiq

      结论:当数据量大到一定程序,请尽量使用原生sql

  • posted @ 2017-05-30 10:32  GXK666  阅读(175)  评论(0编辑  收藏  举报