【发布时间】: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
如何从特定数据库中获取特定表的所有表名和行数?
结果
Table Name , Row Count , Table Size(MB)
---------------------------------------
table_1 , 10 , 2.45
table_2 , 20 , 4.00
【问题讨论】:
标签: mysql ruby-on-rails ruby
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
【讨论】:
该问题已标记为 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_metadata 或 schema_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。谢谢!
我想出了我自己的版本,它也与 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
【讨论】:
@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
【讨论】: