【问题标题】:Fetch all table name and row count for specific table with Rails?使用 Rails 获取特定表的所有表名和行数?
【发布时间】:2011-04-01 04:22:08
【问题描述】:

如何从特定数据库中获取特定表的所有表名和行数?

结果

Table Name , Row Count , Table Size(MB)
---------------------------------------

table_1    , 10        , 2.45

table_2    , 20        , 4.00

【问题讨论】:

    标签: mysql ruby-on-rails ruby


    【解决方案1】:
    ActiveRecord::Base.connection.tables.each do |table|    
     h = ActiveRecord::Base.connection.execute("SHOW TABLE STATUS LIKE '#{table}'").fetch_hash
     puts "#{h['Name']} has #{h['Rows']} rows with size: #{h['Data_length']}"
    end
    

    【讨论】:

    • 显示表状态未使用 InnoDB 返回准确的表行。
    【解决方案2】:

    该问题已标记为 mysql,但您可以通过 ORM 以与 DB 无关的方式进行操作。

    class DatabaseReport
      def entry_counts
        table_model_names.map do |model_name|
          entity = model_name.constantize rescue nil
          next if entity.nil?
          { entity.to_s => entity.count }
        end.compact
      end
    
      private
    
      def table_model_names
        ActiveRecord::Base.connection.tables.map(&:singularize).map(&:camelize)
      end
    end
    

    请注意,这将跳过您没有对象映射的表,例如 ar_internal_metadataschema_migrations 等元表。它也不能推断作用域模型(但可以扩展到这样做)。例如。 Delayed::Job 我这样做:

      def table_model_names
        ActiveRecord::Base.connection.tables.map(&:singularize).map(&:camelize) + ["Delayed::Job"]
      end
    

    【讨论】:

    • 这是正确的做法。我会将entity.all.count 更改为entity.unscoped.count。删除 all 会停止将所有记录加载到内存中,添加 unscoped 会删除任何可能导致数字倾斜的默认范围。
    • all 只是一个范围,在您进一步交互之前它不会运行查询。 all.count 创建计数查询并且不加载所有条目。 entity.count 也可以。默认范围的存在通常是有原因的,所以我不会在通用 SO 响应中搞乱它。 (顺便说一句,应该完全避免使用默认范围,当我问他们时,rubocop 甚至包含一条规则:github.com/rubocop-hq/rubocop-rails/issues/76
    • 我不确定 all 到底是什么。但你是对的,它是延迟加载的。在与之交互并加载之后。它将每个数据库对象加载到内存中。您不需要内存中的每个数据库对象来计算行数。 .count 不会那样做。它只是在桌子上执行一个普通的旧count(*)。虽然默认范围确实不受欢迎。它在框架内有用。即软删除和很好的解释。
    • 如前所述,entity.all.count 不会加载所有实体。它执行COUNT 查询。与where().count相同。
    • 明白了。我将其编辑为entity.count。谢谢!
    【解决方案3】:

    我想出了我自己的版本,它也与 db 无关。

    由于它直接使用后代,它还处理table_name 与模型名称不同的任何表。

    救援nil 存在于当您拥有从 ActiveRecord 继承的类但由于某种原因没有与之关联的表的情况。它确实为 STI 类和父类提供数据。

    my_models = ActiveRecord::Base.descendants
    
    results = my_models.inject({}) do |result, model|
      result[model.name] = model.count rescue nil
      result
    end
    

    【讨论】:

      【解决方案4】:
          @temp_table = []
          ActiveRecord::Base.connection.tables.each do |table|
            count = ActiveRecord::Base.connection.execute("SELECT COUNT(*) as count FROM #{table}").fetch_hash['count']
            size = ActiveRecord::Base.connection.execute("SHOW TABLE STATUS LIKE '#{table}'").fetch_hash
            @temp_table <<  {:table_name => table,
                :records => count.to_i,
                :size_of_table => ((BigDecimal(size['Data_length']) + BigDecimal(size['Index_length']))/1024/1024).round(2)
              }
            end
          end
      

      【讨论】:

        猜你喜欢
        • 2021-10-17
        • 2021-03-22
        • 2015-04-05
        • 2017-05-22
        • 2011-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-20
        • 2011-04-24
        相关资源
        最近更新 更多