From: drh Date: Sat, 19 Jun 2004 11:57:39 +0000 (+0000) Subject: Add the source code to the sqlite_analyzer utility. (CVS 1637) X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=52e50d6aaa64366566b5898fa0d69e1d9c31cf3c;p=thirdparty%2Fsqlite.git Add the source code to the sqlite_analyzer utility. (CVS 1637) FossilOrigin-Name: 06bf4c7e41839eb003f3df05a80789a1f2b21b8f --- diff --git a/main.mk b/main.mk index 2d9f0be502..35715ca163 100644 --- a/main.mk +++ b/main.mk @@ -156,6 +156,20 @@ sqlite$(EXE): $(TOP)/src/shell.c libsqlite.a sqlite.h $(TCCX) $(READLINE_FLAGS) -o sqlite$(EXE) $(TOP)/src/shell.c \ libsqlite.a $(LIBREADLINE) $(THREADLIB) +sqlite_analyzer$(EXE): $(TOP)/src/tclsqlite.c libsqlite.a $(TESTSRC) \ + $(TOP)/tool/spaceanal.tcl + sed \ + -e '/^#/d' \ + -e 's,\\,\\\\,g' \ + -e 's,",\\",g' \ + -e 's,^,",' \ + -e 's,$$,\\n",' \ + $(TOP)/tool/spaceanal.tcl >spaceanal_tcl.h + $(TCCX) $(TCL_FLAGS) -DTCLSH=2 -DSQLITE_TEST=1 -static -o \ + sqlite_analyzer$(EXE) $(TESTSRC) $(TOP)/src/tclsqlite.c \ + libsqlite.a $(LIBTCL) + + # This target creates a directory named "tsrc" and fills it with # copies of all of the C source code and header files needed to # build on the target system. Some of the C source code and header diff --git a/manifest b/manifest index 5a8af495e3..7269a518f7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\scompiler\swarning\sin\sos.c.\s(CVS\s1636) -D 2004-06-19T11:57:08 +C Add\sthe\ssource\scode\sto\sthe\ssqlite_analyzer\sutility.\s(CVS\s1637) +D 2004-06-19T11:57:40 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -15,8 +15,8 @@ F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538 F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826 -F main.mk 1b27efb94be53a96c4333584a00a59fcc87ddc37 -F publish.sh fdad85589c24373715253c88643898255c8aaccd +F main.mk 7dfbd08ac90b15debd84ebd2606f0dbab739a4ab +F publish.sh f163b9aed9367d39350b62e89e799347fcdd01ca F spec.template a38492f1c1dd349fc24cb0565e08afc53045304b F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea F sqlite.def fc4f5734786fe4743cfe2aa98eb2da4b089edb5f @@ -51,7 +51,7 @@ F src/shell.c 920af040d3a33ea8919c82cee45b424ad841cee0 F src/sqlite.h.in 35bec264dfb4965bbfeb7e75221f8658f210c30d F src/sqliteInt.h 235ce244b62bb26cc9ab394fb7a0724dd4e65c83 F src/table.c d845cb101b5afc1f7fea083c99e3d2fa7998d895 -F src/tclsqlite.c 819d92d305756c4ea57de023c387d2fa8a256aff +F src/tclsqlite.c 2daaaa41378fbaf167905363197e1d44464b6eb6 F src/test1.c 4ae20bc125b1a7d7824cccca55d538d81f0b4949 F src/test2.c 75819b0f2c63c6a0fd6995445881f2eb94036996 F src/test3.c 30985ebdfaf3ee1462a9b0652d3efbdc8d9798f5 @@ -159,6 +159,7 @@ F tool/report1.txt 9eae07f26a8fc53889b45fc833a66a33daa22816 F tool/showdb.c 3559eac5a3b46e9b558d50856946b25e77633236 F tool/showjournal.c ec3b171be148656827c4949fbfb8ab4370822f87 F tool/space_used.tcl f714c41a59e326b8b9042f415b628b561bafa06b +F tool/spaceanal.tcl fec9907072011cd2b8b956fe7322cf6c50429ba9 F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf @@ -188,7 +189,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P cce250eaee59eac2d15437b564f049c5b241317c -R 19a887bb25e9741075c84b2d42cd9a5e +P 28b737b5a0e07a142396809f8a7dbd985d433c0d +R fb6b4bcc22cce49b0e4adc90b58e43f9 U drh -Z f4e79bd193b2b10d0f23f1850102fb53 +Z f092da110df516aacd5c626d43efe1ef diff --git a/manifest.uuid b/manifest.uuid index 2197502b52..d3b64433f6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -28b737b5a0e07a142396809f8a7dbd985d433c0d \ No newline at end of file +06bf4c7e41839eb003f3df05a80789a1f2b21b8f \ No newline at end of file diff --git a/publish.sh b/publish.sh index 544ffd33f4..a2cd4e5456 100644 --- a/publish.sh +++ b/publish.sh @@ -26,7 +26,7 @@ chmod +x $srcdir/install-sh VERS=`cat $srcdir/VERSION` VERSW=`sed 's/\./_/g' $srcdir/VERSION` -# Start building stuff. +# Start by building an sqlite shell for linux. # make clean make sqlite @@ -184,7 +184,7 @@ mkdir $HOME/rpm/SRPMS mkdir $HOME/rpm/SPECS # create the spec file from the template -sed s/SQLITE_VERSION/$vers/g $srcdir/spec.template > $HOME/rpm/SPECS/sqlite.spec +sed s/SQLITE_VERSION/$VERS/g $srcdir/spec.template > $HOME/rpm/SPECS/sqlite.spec # copy the source tarball to the rpm directory cp doc/sqlite-$VERS.tar.gz $HOME/rpm/SOURCES/. diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 4e3976478a..2cb5cea4b5 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -11,7 +11,7 @@ ************************************************************************* ** A TCL Interface to SQLite ** -** $Id: tclsqlite.c,v 1.59 2004/02/25 22:51:06 rdc Exp $ +** $Id: tclsqlite.c,v 1.59.2.1 2004/06/19 11:57:40 drh Exp $ */ #ifndef NO_TCL /* Omit this whole file if TCL is unavailable */ @@ -1165,12 +1165,18 @@ int Et_AppInit(Tcl_Interp *interp){ return Sqlite_Init(interp); } #endif +/*************************************************************************** +** The remaining code is only included if the TCLSH macro is defined to +** be an integer greater than 0 +*/ +#if defined(TCLSH) && TCLSH>0 /* ** If the macro TCLSH is defined and is one, then put in code for the -** "main" routine that will initialize Tcl. +** "main" routine that implement a interactive shell into which the user +** can type TCL commands. */ -#if defined(TCLSH) && TCLSH==1 +#if TCLSH==1 static char zMainloop[] = "set line {}\n" "while {![eof stdin]} {\n" @@ -1193,27 +1199,39 @@ static char zMainloop[] = "}\n" "}\n" ; +#endif /* TCLSH==1 */ -#define TCLSH_MAIN main /* Needed to fake out mktclapp */ -int TCLSH_MAIN(int argc, char **argv){ - Tcl_Interp *interp; - Tcl_FindExecutable(argv[0]); - interp = Tcl_CreateInterp(); +int Libsqlite_Init( Tcl_Interp *interp) { +#ifdef TCL_THREADS + if (Thread_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } +#endif Sqlite_Init(interp); #ifdef SQLITE_TEST { extern int Sqlitetest1_Init(Tcl_Interp*); extern int Sqlitetest2_Init(Tcl_Interp*); extern int Sqlitetest3_Init(Tcl_Interp*); - extern int Sqlitetest4_Init(Tcl_Interp*); extern int Md5_Init(Tcl_Interp*); Sqlitetest1_Init(interp); Sqlitetest2_Init(interp); Sqlitetest3_Init(interp); - Sqlitetest4_Init(interp); Md5_Init(interp); + Tcl_StaticPackage(interp, "sqlite", Libsqlite_Init, Libsqlite_Init); } #endif + return TCL_OK; +} + +#define TCLSH_MAIN main /* Needed to fake out mktclapp */ +#if TCLSH==1 +int TCLSH_MAIN(int argc, char **argv){ +#ifndef TCL_THREADS + Tcl_Interp *interp; + Tcl_FindExecutable(argv[0]); + interp = Tcl_CreateInterp(); + Libsqlite_Init(interp); if( argc>=2 ){ int i; Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY); @@ -1226,13 +1244,50 @@ int TCLSH_MAIN(int argc, char **argv){ const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); if( zInfo==0 ) zInfo = interp->result; fprintf(stderr,"%s: %s\n", *argv, zInfo); - return 1; + return TCL_ERROR; } }else{ Tcl_GlobalEval(interp, zMainloop); } return 0; +#else + Tcl_Main(argc, argv, Libsqlite_Init); +#endif /* TCL_THREADS */ + return 0; +} +#endif /* TCLSH==1 */ + + +/* +** If the macro TCLSH is set to 2, then implement a space analysis tool. +*/ +#if TCLSH==2 +static char zAnalysis[] = +#include "spaceanal_tcl.h" +; + +int main(int argc, char **argv){ + Tcl_Interp *interp; + int i; + Tcl_FindExecutable(argv[0]); + interp = Tcl_CreateInterp(); + Libsqlite_Init(interp); + Tcl_SetVar(interp,"argv0",argv[0],TCL_GLOBAL_ONLY); + Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY); + for(i=1; iresult; + fprintf(stderr,"%s: %s\n", *argv, zInfo); + return TCL_ERROR; + } + return 0; } +#endif /* TCLSH==2 */ + #endif /* TCLSH */ -#endif /* !defined(NO_TCL) */ +#endif /* NO_TCL */ diff --git a/tool/spaceanal.tcl b/tool/spaceanal.tcl new file mode 100644 index 0000000000..b9ca2b436b --- /dev/null +++ b/tool/spaceanal.tcl @@ -0,0 +1,436 @@ +# Run this TCL script using "testfixture" in order get a report that shows +# how much disk space is used by a particular data to actually store data +# versus how much space is unused. +# + +# Get the name of the database to analyze +# +if {[llength $argv]!=1} { + puts stderr "Usage: $argv0 database-name" + exit 1 +} +set file_to_analyze [lindex $argv 0] +if {![file exists $file_to_analyze]} { + puts stderr "No such file: $file_to_analyze" + exit 1 +} +if {![file readable $file_to_analyze]} { + puts stderr "File is not readable: $file_to_analyze" + exit 1 +} +if {[file size $file_to_analyze]<2048} { + puts stderr "Empty or malformed database: $file_to_analyze" + exit 1 +} + +# Open the database +# +sqlite db [lindex $argv 0] +set DB [btree_open [lindex $argv 0]] + +# In-memory database for collecting statistics +# +sqlite mem :memory: +set tabledef\ +{CREATE TABLE space_used( + name clob, -- Name of a table or index in the database file + tblname clob, -- Name of associated table + is_index boolean, -- TRUE if it is an index, false for a table + nentry int, -- Number of entries in the BTree + payload int, -- Total amount of data stored in this table or index + mx_payload int, -- Maximum payload size + n_ovfl int, -- Number of entries that overflow + pri_pages int, -- Number of primary pages used + ovfl_pages int, -- Number of overflow pages used + pri_unused int, -- Number of unused bytes on primary pages + ovfl_unused int -- Number of unused bytes on overflow pages +);} +mem eval $tabledef + +# This query will be used to find the root page number for every index and +# table in the database. +# +set sql { + SELECT name, tbl_name, type, rootpage + FROM sqlite_master WHERE type IN ('table','index') + UNION ALL + SELECT 'sqlite_master', 'sqlite_master', 'table', 2 + ORDER BY 1 +} + +# Analyze every table in the database, one at a time. +# +foreach {name tblname type rootpage} [db eval $sql] { + puts stderr "Analyzing $name..." + set cursor [btree_cursor $DB $rootpage 0] + set go [btree_first $cursor] + set size 0 + catch {unset pg_used} + set unused_ovfl 0 + set n_overflow 0 + set cnt_ovfl 0 + set n_entry 0 + set mx_size 0 + set pg_used($rootpage) 1016 + while {$go==0} { + incr n_entry + set payload [btree_payload_size $cursor] + incr size $payload + set stat [btree_cursor_dump $cursor] + set pgno [lindex $stat 0] + set freebytes [lindex $stat 4] + set pg_used($pgno) $freebytes + if {$payload>236} { + # if {[lindex $stat 8]==0} {error "overflow is empty with $payload"} + set n [expr {($payload-236+1019)/1020}] + incr n_overflow $n + incr cnt_ovfl + incr unused_ovfl [expr {$n*1020+236-$payload}] + } else { + # if {[lindex $stat 8]!=0} {error "overflow not empty with $payload"} + } + if {$payload>$mx_size} {set mx_size $payload} + set go [btree_next $cursor] + } + btree_close_cursor $cursor + set n_primary [llength [array names pg_used]] + set unused_primary 0 + foreach x [array names pg_used] {incr unused_primary $pg_used($x)} + regsub -all ' $name '' name + set sql "INSERT INTO space_used VALUES('$name'" + regsub -all ' $tblname '' tblname + append sql ",'$tblname',[expr {$type=="index"}],$n_entry" + append sql ",$size,$mx_size,$cnt_ovfl," + append sql "$n_primary,$n_overflow,$unused_primary,$unused_ovfl);" + mem eval $sql +} + +# Generate a single line of output in the statistics section of the +# report. +# +proc statline {title value {extra {}}} { + set len [string length $title] + set dots [string range {......................................} $len end] + set len [string length $value] + set sp2 [string range { } $len end] + if {$extra ne ""} { + set extra " $extra" + } + puts "$title$dots $value$sp2$extra" +} + +# Generate a formatted percentage value for $num/$denom +# +proc percent {num denom} { + if {$denom==0.0} {return ""} + set v [expr {$num*100.0/$denom}] + if {$v>1.0 && $v<99.0} { + return [format %4.1f%% $v] + } elseif {$v<0.1 || $v>99.9} { + return [format %6.3f%% $v] + } else { + return [format %5.2f%% $v] + } +} + +# Generate a subreport that covers some subset of the database. +# the $where clause determines which subset to analyze. +# +proc subreport {title where} { + set hit 0 + mem eval "SELECT sum(nentry) AS nentry, \ + sum(payload) AS payload, \ + sum(CASE is_index WHEN 1 THEN 0 ELSE payload-4*nentry END) \ + AS data, \ + max(mx_payload) AS mx_payload, \ + sum(n_ovfl) as n_ovfl, \ + sum(pri_pages) AS pri_pages, \ + sum(ovfl_pages) AS ovfl_pages, \ + sum(pri_unused) AS pri_unused, \ + sum(ovfl_unused) AS ovfl_unused \ + FROM space_used WHERE $where" {} {set hit 1} + if {!$hit} {return 0} + puts "" + set len [string length $title] + incr len 5 + set stars "***********************************" + append stars $stars + set stars [string range $stars $len end] + puts "*** $title $stars" + puts "" + statline "Percentage of total database" \ + [percent [expr {$pri_pages+$ovfl_pages}] $::file_pgcnt] + statline "Number of entries" $nentry + set storage [expr {($pri_pages+$ovfl_pages)*1024}] + statline "Bytes of storage consumed" $storage + statline "Bytes of payload" $payload [percent $payload $storage] + statline "Bytes of data" $data [percent $data $storage] + set key [expr {$payload-$data}] + statline "Bytes of key" $key [percent $key $storage] + set avgpay [expr {$nentry>0?$payload/$nentry:0}] + statline "Average payload per entry" $avgpay + set avgunused [expr {$nentry>0?($pri_unused+$ovfl_unused)/$nentry:0}] + statline "Average unused bytes per entry" $avgunused + statline "Average fanout" \ + [format %.2f [expr {$pri_pages==0?0:($nentry+0.0)/$pri_pages}]] + statline "Maximum payload per entry" $mx_payload + statline "Entries that use overflow" $n_ovfl [percent $n_ovfl $nentry] + statline "Total pages used" [set allpgs [expr {$pri_pages+$ovfl_pages}]] + statline "Primary pages used" $pri_pages ;# [percent $pri_pages $allpgs] + statline "Overflow pages used" $ovfl_pages ;# [percent $ovfl_pages $allpgs] + statline "Unused bytes on primary pages" $pri_unused \ + [percent $pri_unused [expr {$pri_pages*1024}]] + statline "Unused bytes on overflow pages" $ovfl_unused \ + [percent $ovfl_unused [expr {$ovfl_pages*1024}]] + set allunused [expr {$ovfl_unused+$pri_unused}] + statline "Unused bytes on all pages" $allunused \ + [percent $allunused [expr {$allpgs*1024}]] + return 1 +} + +# Output summary statistics: +# +puts "/** Disk-Space Utilization Report For $file_to_analyze" +puts "*** As of [clock format [clock seconds] -format {%Y-%b-%d %H:%M:%S}]" +puts "" +set fsize [file size [lindex $argv 0]] +set file_pgcnt [expr {$fsize/1024}] +set usedcnt [mem eval {SELECT sum(pri_pages+ovfl_pages) FROM space_used}] +set freecnt [expr {$file_pgcnt-$usedcnt-1}] +set freecnt2 [lindex [btree_get_meta $DB] 0] +statline {Pages in the whole file (measured)} $file_pgcnt +set file_pgcnt2 [expr {$usedcnt+$freecnt2+1}] +statline {Pages in the whole file (calculated)} $file_pgcnt2 +statline {Pages that store data} $usedcnt [percent $usedcnt $file_pgcnt] +statline {Pages on the freelist (per header)}\ + $freecnt2 [percent $freecnt2 $file_pgcnt] +statline {Pages on the freelist (calculated)}\ + $freecnt [percent $freecnt $file_pgcnt] +statline {Header pages} 1 [percent 1 $file_pgcnt] + +set ntable [db eval {SELECT count(*)+1 FROM sqlite_master WHERE type='table'}] +statline {Number of tables in the database} $ntable +set nindex [db eval {SELECT count(*) FROM sqlite_master WHERE type='index'}] +set autoindex [db eval {SELECT count(*) FROM sqlite_master + WHERE type='index' AND name LIKE '(% autoindex %)'}] +set manindex [expr {$nindex-$autoindex}] +statline {Number of indices} $nindex +statline {Number of named indices} $manindex [percent $manindex $nindex] +statline {Automatically generated indices} $autoindex \ + [percent $autoindex $nindex] + +set bytes_data [mem eval "SELECT sum(payload-4*nentry) FROM space_used + WHERE NOT is_index AND name!='sqlite_master'"] +set total_payload [mem eval "SELECT sum(payload) FROM space_used"] +statline "Size of the file in bytes" $fsize +statline "Bytes of payload stored" $total_payload \ + [percent $total_payload $fsize] +statline "Bytes of user data stored" $bytes_data \ + [percent $bytes_data $fsize] + +# Output table rankings +# +puts "" +puts "*** Page counts for all tables with their indices ********************" +puts "" +mem eval {SELECT tblname, count(*) AS cnt, sum(pri_pages+ovfl_pages) AS size + FROM space_used GROUP BY tblname ORDER BY size DESC, tblname} {} { + statline [string toupper $tblname] $size [percent $size $file_pgcnt] +} + +# Output subreports +# +if {$nindex>0} { + subreport {All tables and indices} 1 +} +subreport {All tables} {NOT is_index} +if {$nindex>0} { + subreport {All indices} {is_index} +} +foreach tbl [mem eval {SELECT name FROM space_used WHERE NOT is_index + ORDER BY name}] { + regsub ' $tbl '' qn + set name [string toupper $tbl] + set n [mem eval "SELECT count(*) FROM space_used WHERE tblname='$qn'"] + if {$n>1} { + subreport "Table $name and all its indices" "tblname='$qn'" + subreport "Table $name w/o any indices" "name='$qn'" + subreport "Indices of table $name" "tblname='$qn' AND is_index" + } else { + subreport "Table $name" "name='$qn'" + } +} + +# Output instructions on what the numbers above mean. +# +puts { +*** Definitions ****************************************************** + +Number of pages in the whole file + + The number of 1024-byte pages that go into forming the complete database + +Pages that store data + + The number of pages that store data, either as primary B*Tree pages or + as overflow pages. The number at the right is the data pages divided by + the total number of pages in the file. + +Pages on the freelist + + The number of pages that are not currently in use but are reserved for + future use. The percentage at the right is the number of freelist pages + divided by the total number of pages in the file. + +Header pages + + The number of pages of header overhead in the database. This value is + always 1. The percentage at the right is the number of header pages + divided by the total number of pages in the file. + +Number of tables in the database + + The number of tables in the database, including the SQLITE_MASTER table + used to store schema information. + +Number of indices + + The total number of indices in the database. + +Number of named indices + + The number of indices created using an explicit CREATE INDEX statement. + +Automatically generated indices + + The number of indices used to implement PRIMARY KEY or UNIQUE constraints + on tables. + +Size of the file in bytes + + The total amount of disk space used by the entire database files. + +Bytes of payload stored + + The total number of bytes of payload stored in the database. Payload + includes both key and data. The content of the SQLITE_MASTER table is + counted when computing this number. The percentage at the right shows + the payload divided by the total file size. + +Bytes of user data stored + + The total number of bytes of data stored in the database, not counting + the database schema information stored in the SQLITE_MASTER table. The + percentage at the right is the user data size divided by the total file + size. + +Percentage of total database + + The amount of the complete database file that is devoted to storing + information described by this category. + +Number of entries + + The total number of B*Tree key/value pairs stored under this category. + +Bytes of storage consumed + + The total amount of disk space required to store all B*Tree entries + under this category. The is the total number of pages used times + the pages size (1024). + +Bytes of payload + + The amount of payload stored under this category. Payload is the sum + of keys and data. Each table entry has 4 bytes of key and an arbitrary + amount of data. Each index entry has 4 or more bytes of key and no + data. The percentage at the right is the bytes of payload divided by + the bytes of storage consumed. + +Bytes of data + + The amount of data stored under this category. The data space reported + includes formatting information such as nul-terminators and field-lengths + that are stored with the data. The percentage at the right is the bytes + of data divided by bytes of storage consumed. + +Bytes of key + + The sum of the sizes of all keys under this category. The percentage at + the right is the bytes of key divided by the bytes of storage consumed. + +Average payload per entry + + The average amount of payload on each entry. This is just the bytes of + payload divided by the number of entries. + +Average unused bytes per entry + + The average amount of free space remaining on all pages under this + category on a per-entry basis. This is the number of unused bytes on + all pages divided by the number of entries. + +Maximum payload per entry + + The largest payload size of any entry. + +Entries that use overflow + + Up to 236 bytes of payload for each entry are stored directly in the + primary B*Tree page. Any additional payload is stored on a linked list + of overflow pages. This is the number of entries that exceed 236 bytes + in size. The value to the right is the number of entries that overflow + divided by the total number of entries. + +Total pages used + + This is the number of 1024 byte pages used to hold all information in + the current category. This is the sum of primary and overflow pages. + +Primary pages used + + This is the number of primary B*Tree pages used. + +Overflow pages used + + The total number of overflow pages used for this category. + +Unused bytes on primary pages + + The total number of bytes of unused space on all primary pages. The + percentage at the right is the number of unused bytes divided by the + total number of bytes on primary pages. + +Unused bytes on overflow pages + + The total number of bytes of unused space on all overflow pages. The + percentage at the right is the number of unused bytes divided by the + total number of bytes on overflow pages. + +Unused bytes on all pages + + The total number of bytes of unused space on all primary and overflow + pages. The percentage at the right is the number of unused bytes + divided by the total number of bytes. +} + +# Output the database +# +puts "**********************************************************************" +puts "The entire text of this report can be sourced into any SQL database" +puts "engine for further analysis. All of the text above is an SQL comment." +puts "The data used to generate this report follows:" +puts "*/" +puts "BEGIN;" +puts $tabledef +unset -nocomplain x +mem eval {SELECT * FROM space_used} x { + puts -nonewline "INSERT INTO space_used VALUES(" + regsub ' $x(name) '' qn + regsub ' $x(tblname) '' qtn + puts -nonewline "'$qn','$qtn'," + puts -nonewline "$x(is_index),$x(nentry),$x(payload),$x(mx_payload)," + puts -nonewline "$x(n_ovfl),$x(pri_pages),$x(ovfl_pages),$x(pri_unused)," + puts "$x(ovfl_unused));" +} +puts "COMMIT;"