xref: /titanic_52/usr/src/lib/libsqlite/tool/space_used.tcl (revision c5c4113dfcabb1eed3d4bdf7609de5170027a794)
1*c5c4113dSnw141292
2*c5c4113dSnw141292#pragma ident	"%Z%%M%	%I%	%E% SMI"
3*c5c4113dSnw141292
4*c5c4113dSnw141292# Run this TCL script using "testfixture" in order get a report that shows
5*c5c4113dSnw141292# how much disk space is used by a particular data to actually store data
6*c5c4113dSnw141292# versus how much space is unused.
7*c5c4113dSnw141292#
8*c5c4113dSnw141292
9*c5c4113dSnw141292# Get the name of the database to analyze
10*c5c4113dSnw141292#
11*c5c4113dSnw141292if {[llength $argv]!=1} {
12*c5c4113dSnw141292  puts stderr "Usage: $argv0 database-name"
13*c5c4113dSnw141292  exit 1
14*c5c4113dSnw141292}
15*c5c4113dSnw141292set file_to_analyze [lindex $argv 0]
16*c5c4113dSnw141292
17*c5c4113dSnw141292# Open the database
18*c5c4113dSnw141292#
19*c5c4113dSnw141292sqlite db [lindex $argv 0]
20*c5c4113dSnw141292set DB [btree_open [lindex $argv 0]]
21*c5c4113dSnw141292
22*c5c4113dSnw141292# Output the schema for the generated report
23*c5c4113dSnw141292#
24*c5c4113dSnw141292puts \
25*c5c4113dSnw141292{BEGIN;
26*c5c4113dSnw141292CREATE TABLE space_used(
27*c5c4113dSnw141292   name clob,        -- Name of a table or index in the database file
28*c5c4113dSnw141292   is_index boolean, -- TRUE if it is an index, false for a table
29*c5c4113dSnw141292   payload int,      -- Total amount of data stored in this table or index
30*c5c4113dSnw141292   pri_pages int,    -- Number of primary pages used
31*c5c4113dSnw141292   ovfl_pages int,   -- Number of overflow pages used
32*c5c4113dSnw141292   pri_unused int,   -- Number of unused bytes on primary pages
33*c5c4113dSnw141292   ovfl_unused int   -- Number of unused bytes on overflow pages
34*c5c4113dSnw141292);}
35*c5c4113dSnw141292
36*c5c4113dSnw141292# This query will be used to find the root page number for every index and
37*c5c4113dSnw141292# table in the database.
38*c5c4113dSnw141292#
39*c5c4113dSnw141292set sql {
40*c5c4113dSnw141292  SELECT name, type, rootpage FROM sqlite_master
41*c5c4113dSnw141292  UNION ALL
42*c5c4113dSnw141292  SELECT 'sqlite_master', 'table', 2
43*c5c4113dSnw141292  ORDER BY 1
44*c5c4113dSnw141292}
45*c5c4113dSnw141292
46*c5c4113dSnw141292# Initialize variables used for summary statistics.
47*c5c4113dSnw141292#
48*c5c4113dSnw141292set total_size 0
49*c5c4113dSnw141292set total_primary 0
50*c5c4113dSnw141292set total_overflow 0
51*c5c4113dSnw141292set total_unused_primary 0
52*c5c4113dSnw141292set total_unused_ovfl 0
53*c5c4113dSnw141292
54*c5c4113dSnw141292# Analyze every table in the database, one at a time.
55*c5c4113dSnw141292#
56*c5c4113dSnw141292foreach {name type rootpage} [db eval $sql] {
57*c5c4113dSnw141292  set cursor [btree_cursor $DB $rootpage 0]
58*c5c4113dSnw141292  set go [btree_first $cursor]
59*c5c4113dSnw141292  set size 0
60*c5c4113dSnw141292  catch {unset pg_used}
61*c5c4113dSnw141292  set unused_ovfl 0
62*c5c4113dSnw141292  set n_overflow 0
63*c5c4113dSnw141292  while {$go==0} {
64*c5c4113dSnw141292    set payload [btree_payload_size $cursor]
65*c5c4113dSnw141292    incr size $payload
66*c5c4113dSnw141292    set stat [btree_cursor_dump $cursor]
67*c5c4113dSnw141292    set pgno [lindex $stat 0]
68*c5c4113dSnw141292    set freebytes [lindex $stat 4]
69*c5c4113dSnw141292    set pg_used($pgno) $freebytes
70*c5c4113dSnw141292    if {$payload>238} {
71*c5c4113dSnw141292      set n [expr {($payload-238+1019)/1020}]
72*c5c4113dSnw141292      incr n_overflow $n
73*c5c4113dSnw141292      incr unused_ovfl [expr {$n*1020+238-$payload}]
74*c5c4113dSnw141292    }
75*c5c4113dSnw141292    set go [btree_next $cursor]
76*c5c4113dSnw141292  }
77*c5c4113dSnw141292  btree_close_cursor $cursor
78*c5c4113dSnw141292  set n_primary [llength [array names pg_used]]
79*c5c4113dSnw141292  set unused_primary 0
80*c5c4113dSnw141292  foreach x [array names pg_used] {incr unused_primary $pg_used($x)}
81*c5c4113dSnw141292  regsub -all ' $name '' name
82*c5c4113dSnw141292  puts -nonewline "INSERT INTO space_used VALUES('$name'"
83*c5c4113dSnw141292  puts -nonewline ",[expr {$type=="index"}]"
84*c5c4113dSnw141292  puts ",$size,$n_primary,$n_overflow,$unused_primary,$unused_ovfl);"
85*c5c4113dSnw141292  incr total_size $size
86*c5c4113dSnw141292  incr total_primary $n_primary
87*c5c4113dSnw141292  incr total_overflow $n_overflow
88*c5c4113dSnw141292  incr total_unused_primary $unused_primary
89*c5c4113dSnw141292  incr total_unused_ovfl $unused_ovfl
90*c5c4113dSnw141292}
91*c5c4113dSnw141292
92*c5c4113dSnw141292# Output summary statistics:
93*c5c4113dSnw141292#
94*c5c4113dSnw141292puts "-- Total payload size: $total_size"
95*c5c4113dSnw141292puts "-- Total pages used: $total_primary primary and $total_overflow overflow"
96*c5c4113dSnw141292set file_pgcnt [expr {[file size [lindex $argv 0]]/1024}]
97*c5c4113dSnw141292puts -nonewline "-- Total unused bytes on primary pages: $total_unused_primary"
98*c5c4113dSnw141292if {$total_primary>0} {
99*c5c4113dSnw141292  set upp [expr {$total_unused_primary/$total_primary}]
100*c5c4113dSnw141292  puts " (avg $upp bytes/page)"
101*c5c4113dSnw141292} else {
102*c5c4113dSnw141292  puts ""
103*c5c4113dSnw141292}
104*c5c4113dSnw141292puts -nonewline "-- Total unused bytes on overflow pages: $total_unused_ovfl"
105*c5c4113dSnw141292if {$total_overflow>0} {
106*c5c4113dSnw141292  set upp [expr {$total_unused_ovfl/$total_overflow}]
107*c5c4113dSnw141292  puts " (avg $upp bytes/page)"
108*c5c4113dSnw141292} else {
109*c5c4113dSnw141292  puts ""
110*c5c4113dSnw141292}
111*c5c4113dSnw141292set n_free [expr {$file_pgcnt-$total_primary-$total_overflow}]
112*c5c4113dSnw141292if {$n_free>0} {incr n_free -1}
113*c5c4113dSnw141292puts "-- Total pages on freelist: $n_free"
114*c5c4113dSnw141292puts "COMMIT;"
115