【问题标题】:Recalculate Counter Cache of 120k Records [Rails / ActiveRecord]重新计算 120k 记录的计数器缓存 [Rails / ActiveRecord]
【发布时间】:2010-05-06 17:07:16
【问题描述】:

以下情况:

我有一个 poi 模型,里面有很多图片 (1:n)。我想重新计算 counter_cache 列,因为值不一致。

我尝试在 ruby​​ 中对每条记录进行迭代,但这花费的时间太长,并且有时会因一些“分段错误”错误而退出。

所以我想知道,是否可以使用原始 sql 查询来做到这一点?

【问题讨论】:

    标签: mysql ruby-on-rails activerecord


    【解决方案1】:

    例如,如果您有PostPicture 模型,并发布has_many :pictures,您可以使用update_all 来完成:

    Post.update_all("pictures_count=(Select count(*) from pictures where pictures.post_id=posts.id)")
    

    【讨论】:

      【解决方案2】:

      我在 krautcomputing 上找到了一个不错的解决方案。
      它使用反射查找项目的所有计数器缓存,使用 SQL 查询仅查找不一致的对象,并使用 Rails reset_counters 进行清理。

      不幸的是,它只适用于“常规”计数器缓存(没有类名,没有自定义计数器缓存名称),所以我对其进行了改进:

      Rails.application.eager_load!
      
      ActiveRecord::Base.descendants.each do |many_class|
        many_class.reflections.each do |name, reflection|
          if reflection.options[:counter_cache]
            one_class = reflection.class_name.constantize
            one_table, many_table = [one_class, many_class].map(&:table_name)
            # more reflections, use :inverse_of, :counter_cache etc.
            inverse_of = reflection.options[:inverse_of]
            counter_cache = reflection.options[:counter_cache]
            if counter_cache === true
              counter_cache = "#{many_table}_count"
              inverse_of ||= many_table.to_sym
            else
              inverse_of ||= counter_cache.to_s.sub(/_count$/,'').to_sym
            end
            ids = one_class
              .joins(inverse_of)
              .group("#{one_table}.id")
              .having("MAX(#{one_table}.#{counter_cache}) != COUNT(#{many_table}.id)")
              .pluck("#{one_table}.id")
            ids.each do |id|
              puts "reset #{id} on #{many_table}"
              one_class.reset_counters id, inverse_of
            end
          end
        end
      end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-10-26
        • 1970-01-01
        • 1970-01-01
        • 2014-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多