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