File: disk_usage_report.rb

package info (click to toggle)
ruby-pg 1.5.6-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,264 kB
  • sloc: ansic: 8,820; ruby: 2,809; makefile: 10
file content (177 lines) | stat: -rw-r--r-- 3,658 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# -*- ruby -*-
# vim: set noet nosta sw=4 ts=4 :
#
# Quickly dump size information for a given database.
# Top twenty objects, and size per schema.
#
# Mahlon E. Smith <mahlon@martini.nu>
#
# Based on work by Jeff Davis <ruby@j-davis.com>.
#


require 'ostruct'
require 'optparse'
require 'etc'
require 'pg'

SCRIPT_VERSION = %q$Id$


### Gather data and output it to $stdout.
###
def report( opts )
	db = PG.connect(
		:dbname   => opts.database,
		:host     => opts.host,
		:port     => opts.port,
		:user     => opts.user,
		:password => opts.pass,
		:sslmode  => 'prefer'
	)

	# -----------------------------------------

	db_info = db.exec %Q{
		SELECT
			count(oid) AS num_relations,
			pg_size_pretty(pg_database_size('#{opts.database}')) AS dbsize
		FROM
			pg_class
	}

	puts '=' * 70
	puts "Disk usage information for %s: (%d relations, %s total)" % [
		opts.database,
		db_info[0]['num_relations'],
		db_info[0]['dbsize']
	]
	puts '=' * 70

	# -----------------------------------------

	top_twenty = db.exec %q{
		SELECT
			relname AS name,
			relkind AS kind,
			pg_size_pretty(pg_relation_size(pg_class.oid)) AS size
		FROM
			pg_class
		ORDER BY
			pg_relation_size(pg_class.oid) DESC
		LIMIT 20
	}

	puts 'Top twenty objects by size:'
	puts '-' * 70
	top_twenty.each do |row|
		type = case row['kind']
			   when 'i'; 'index'
			   when 't'; 'toast'
			   when 'r'; 'table'
			   when 'S'; 'sequence'
			   else;     '???'
			   end

		puts "%40s %10s (%s)" % [ row['name'], row['size'], type ]
	end
	puts '-' * 70

	# -----------------------------------------

	schema_sizes = db.exec %q{
		SELECT
			table_schema,
			pg_size_pretty( CAST( SUM(pg_total_relation_size(table_schema || '.' || table_name)) AS bigint)) AS size
		FROM
			information_schema.tables
		GROUP BY
			table_schema
		ORDER BY
			CAST( SUM(pg_total_relation_size(table_schema || '.' || table_name)) AS bigint ) DESC
	}


	puts 'Size per schema:'
	puts '-' * 70
	schema_sizes.each do |row|
		puts "%20s %10s" % [ row['table_schema'], row['size'] ]
	end
	puts '-' * 70
	puts

	db.finish
end


### Parse command line arguments.  Return a struct of global options.
###
def parse_args( args )
	options          = OpenStruct.new
	options.database = Etc.getpwuid( Process.uid ).name
	options.host     = '127.0.0.1'
	options.port     = 5432
	options.user     = Etc.getpwuid( Process.uid ).name
	options.sslmode  = 'prefer'
	options.interval = 5

	opts = OptionParser.new do |opts|
		opts.banner = "Usage: #{$0} [options]"

		opts.separator ''
		opts.separator 'Connection options:'

		opts.on( '-d', '--database DBNAME',
				"specify the database to connect to (default: \"#{options.database}\")" ) do |db|
			options.database = db
		end

		opts.on( '-h', '--host HOSTNAME', 'database server host' ) do |host|
			options.host = host
		end

		opts.on( '-p', '--port PORT', Integer,
				"database server port (default: \"#{options.port}\")" ) do |port|
			options.port = port
		end

		opts.on( '-U', '--user NAME',
				"database user name (default: \"#{options.user}\")" ) do |user|
			options.user = user
		end

		opts.on( '-W', 'force password prompt' ) do |pw|
			print 'Password: '
			begin
				system 'stty -echo'
				options.pass = gets.chomp
			ensure
				system 'stty echo'
				puts
			end
		end

		opts.separator ''
		opts.separator 'Other options:'

		opts.on_tail( '--help', 'show this help, then exit' ) do
			$stderr.puts opts
			exit
		end

		opts.on_tail( '--version', 'output version information, then exit' ) do
			puts SCRIPT_VERSION
			exit
		end
	end

	opts.parse!( args )
	return options
end


if __FILE__ == $0
	opts = parse_args( ARGV )
	report( opts )
end