1*4c68e6d2Sdrh# 2008 March 21 2*4c68e6d2Sdrh# 3*4c68e6d2Sdrh# The author disclaims copyright to this source code. In place of 4*4c68e6d2Sdrh# a legal notice, here is a blessing: 5*4c68e6d2Sdrh# 6*4c68e6d2Sdrh# May you do good and not evil. 7*4c68e6d2Sdrh# May you find forgiveness for yourself and forgive others. 8*4c68e6d2Sdrh# May you share freely, never taking more than you give. 9*4c68e6d2Sdrh# 10*4c68e6d2Sdrh#************************************************************************* 11*4c68e6d2Sdrh# This file implements regression tests for SQLite library. The 12*4c68e6d2Sdrh# focus of this script is measuring executing speed. 13*4c68e6d2Sdrh# 14*4c68e6d2Sdrh# This is a copy of speed1.test modified to user prepared statements. 15*4c68e6d2Sdrh# 16*4c68e6d2Sdrh# $Id: speed1p.explain,v 1.1 2008/04/16 12:57:48 drh Exp $ 17*4c68e6d2Sdrh# 18*4c68e6d2Sdrh 19*4c68e6d2Sdrhset testdir [file dirname $argv0] 20*4c68e6d2Sdrhsource $testdir/tester.tcl 21*4c68e6d2Sdrhspeed_trial_init speed1 22*4c68e6d2Sdrh 23*4c68e6d2Sdrh# Set a uniform random seed 24*4c68e6d2Sdrhexpr srand(0) 25*4c68e6d2Sdrh 26*4c68e6d2Sdrhset sqlout [open speed1.txt w] 27*4c68e6d2Sdrhproc tracesql {sql} { 28*4c68e6d2Sdrh puts $::sqlout $sql\; 29*4c68e6d2Sdrh} 30*4c68e6d2Sdrh#db trace tracesql 31*4c68e6d2Sdrh 32*4c68e6d2Sdrh# The number_name procedure below converts its argment (an integer) 33*4c68e6d2Sdrh# into a string which is the English-language name for that number. 34*4c68e6d2Sdrh# 35*4c68e6d2Sdrh# Example: 36*4c68e6d2Sdrh# 37*4c68e6d2Sdrh# puts [number_name 123] -> "one hundred twenty three" 38*4c68e6d2Sdrh# 39*4c68e6d2Sdrhset ones {zero one two three four five six seven eight nine 40*4c68e6d2Sdrh ten eleven twelve thirteen fourteen fifteen sixteen seventeen 41*4c68e6d2Sdrh eighteen nineteen} 42*4c68e6d2Sdrhset tens {{} ten twenty thirty forty fifty sixty seventy eighty ninety} 43*4c68e6d2Sdrhproc number_name {n} { 44*4c68e6d2Sdrh if {$n>=1000} { 45*4c68e6d2Sdrh set txt "[number_name [expr {$n/1000}]] thousand" 46*4c68e6d2Sdrh set n [expr {$n%1000}] 47*4c68e6d2Sdrh } else { 48*4c68e6d2Sdrh set txt {} 49*4c68e6d2Sdrh } 50*4c68e6d2Sdrh if {$n>=100} { 51*4c68e6d2Sdrh append txt " [lindex $::ones [expr {$n/100}]] hundred" 52*4c68e6d2Sdrh set n [expr {$n%100}] 53*4c68e6d2Sdrh } 54*4c68e6d2Sdrh if {$n>=20} { 55*4c68e6d2Sdrh append txt " [lindex $::tens [expr {$n/10}]]" 56*4c68e6d2Sdrh set n [expr {$n%10}] 57*4c68e6d2Sdrh } 58*4c68e6d2Sdrh if {$n>0} { 59*4c68e6d2Sdrh append txt " [lindex $::ones $n]" 60*4c68e6d2Sdrh } 61*4c68e6d2Sdrh set txt [string trim $txt] 62*4c68e6d2Sdrh if {$txt==""} {set txt zero} 63*4c68e6d2Sdrh return $txt 64*4c68e6d2Sdrh} 65*4c68e6d2Sdrh 66*4c68e6d2Sdrh# Create a database schema. 67*4c68e6d2Sdrh# 68*4c68e6d2Sdrhdo_test speed1p-1.0 { 69*4c68e6d2Sdrh execsql { 70*4c68e6d2Sdrh PRAGMA page_size=1024; 71*4c68e6d2Sdrh PRAGMA cache_size=8192; 72*4c68e6d2Sdrh PRAGMA locking_mode=EXCLUSIVE; 73*4c68e6d2Sdrh CREATE TABLE t1(a INTEGER, b INTEGER, c TEXT); 74*4c68e6d2Sdrh CREATE TABLE t2(a INTEGER, b INTEGER, c TEXT); 75*4c68e6d2Sdrh CREATE INDEX i2a ON t2(a); 76*4c68e6d2Sdrh CREATE INDEX i2b ON t2(b); 77*4c68e6d2Sdrh } 78*4c68e6d2Sdrh execsql { 79*4c68e6d2Sdrh SELECT name FROM sqlite_master ORDER BY 1; 80*4c68e6d2Sdrh } 81*4c68e6d2Sdrh} {i2a i2b t1 t2} 82*4c68e6d2Sdrh 83*4c68e6d2Sdrh 84*4c68e6d2Sdrh# 50000 INSERTs on an unindexed table 85*4c68e6d2Sdrh# 86*4c68e6d2Sdrhset list {} 87*4c68e6d2Sdrhfor {set i 1} {$i<=50000} {incr i} { 88*4c68e6d2Sdrh set r [expr {int(rand()*500000)}] 89*4c68e6d2Sdrh set x [number_name $r] 90*4c68e6d2Sdrh lappend list $i $r $x 91*4c68e6d2Sdrh} 92*4c68e6d2Sdrhset script { 93*4c68e6d2Sdrh foreach {i r x} $::list { 94*4c68e6d2Sdrh db eval {INSERT INTO t1 VALUES($i,$r,$x)} 95*4c68e6d2Sdrh } 96*4c68e6d2Sdrh} 97*4c68e6d2Sdrhexplain {INSERT INTO t1 VALUES($i,$r,$x)} 98*4c68e6d2Sdrhdb eval BEGIN 99*4c68e6d2Sdrhspeed_trial_tcl speed1p-insert1 50000 row $script 100*4c68e6d2Sdrhdb eval COMMIT 101*4c68e6d2Sdrh 102*4c68e6d2Sdrh# 50000 INSERTs on an indexed table 103*4c68e6d2Sdrh# 104*4c68e6d2Sdrhset list {} 105*4c68e6d2Sdrhfor {set i 1} {$i<=50000} {incr i} { 106*4c68e6d2Sdrh set r [expr {int(rand()*500000)}] 107*4c68e6d2Sdrh set x [number_name $r] 108*4c68e6d2Sdrh lappend list $i $r $x 109*4c68e6d2Sdrh} 110*4c68e6d2Sdrhset script { 111*4c68e6d2Sdrh foreach {i r x} $::list { 112*4c68e6d2Sdrh db eval {INSERT INTO t2 VALUES($i,$r,$x)} 113*4c68e6d2Sdrh } 114*4c68e6d2Sdrh} 115*4c68e6d2Sdrhexplain {INSERT INTO t2 VALUES($i,$r,$x)} 116*4c68e6d2Sdrhdb eval BEGIN 117*4c68e6d2Sdrhspeed_trial_tcl speed1p-insert2 50000 row $script 118*4c68e6d2Sdrhdb eval COMMIT 119*4c68e6d2Sdrh 120*4c68e6d2Sdrh 121*4c68e6d2Sdrh 122*4c68e6d2Sdrh# 50 SELECTs on an integer comparison. There is no index so 123*4c68e6d2Sdrh# a full table scan is required. 124*4c68e6d2Sdrh# 125*4c68e6d2Sdrhset list {} 126*4c68e6d2Sdrhfor {set i 0} {$i<50} {incr i} { 127*4c68e6d2Sdrh set lwr [expr {$i*100}] 128*4c68e6d2Sdrh set upr [expr {($i+10)*100}] 129*4c68e6d2Sdrh lappend list $lwr $upr 130*4c68e6d2Sdrh} 131*4c68e6d2Sdrhset script { 132*4c68e6d2Sdrh foreach {lwr upr} $::list { 133*4c68e6d2Sdrh db eval {SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr} 134*4c68e6d2Sdrh } 135*4c68e6d2Sdrh} 136*4c68e6d2Sdrhexplain {SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr} 137*4c68e6d2Sdrhdb eval BEGIN 138*4c68e6d2Sdrhspeed_trial_tcl speed1p-select1 [expr {50*50000}] row $script 139*4c68e6d2Sdrhdb eval COMMIT 140*4c68e6d2Sdrh 141*4c68e6d2Sdrh# 50 SELECTs on an LIKE comparison. There is no index so a full 142*4c68e6d2Sdrh# table scan is required. 143*4c68e6d2Sdrh# 144*4c68e6d2Sdrhset list {} 145*4c68e6d2Sdrhfor {set i 0} {$i<50} {incr i} { 146*4c68e6d2Sdrh lappend list "%[number_name $i]%" 147*4c68e6d2Sdrh} 148*4c68e6d2Sdrhset script { 149*4c68e6d2Sdrh foreach pattern $::list { 150*4c68e6d2Sdrh db eval {SELECT count(*), avg(b) FROM t1 WHERE c LIKE $pattern} 151*4c68e6d2Sdrh } 152*4c68e6d2Sdrh} 153*4c68e6d2Sdrhexplain {SELECT count(*), avg(b) FROM t1 WHERE c LIKE $pattern} 154*4c68e6d2Sdrhdb eval BEGIN 155*4c68e6d2Sdrhspeed_trial_tcl speed1p-select2 [expr {50*50000}] row $script 156*4c68e6d2Sdrhdb eval COMMIT 157*4c68e6d2Sdrh 158*4c68e6d2Sdrh# Create indices 159*4c68e6d2Sdrh# 160*4c68e6d2Sdrhexplain {CREATE INDEX i1a ON t1(a)} 161*4c68e6d2Sdrhexplain {CREATE INDEX i1b ON t1(b)} 162*4c68e6d2Sdrhdb eval BEGIN 163*4c68e6d2Sdrhspeed_trial speed1p-createidx 150000 row { 164*4c68e6d2Sdrh CREATE INDEX i1a ON t1(a); 165*4c68e6d2Sdrh CREATE INDEX i1b ON t1(b); 166*4c68e6d2Sdrh CREATE INDEX i1c ON t1(c); 167*4c68e6d2Sdrh} 168*4c68e6d2Sdrhdb eval COMMIT 169*4c68e6d2Sdrh 170*4c68e6d2Sdrh# 5000 SELECTs on an integer comparison where the integer is 171*4c68e6d2Sdrh# indexed. 172*4c68e6d2Sdrh# 173*4c68e6d2Sdrhset list {} 174*4c68e6d2Sdrhfor {set i 0} {$i<5000} {incr i} { 175*4c68e6d2Sdrh set lwr [expr {$i*100}] 176*4c68e6d2Sdrh set upr [expr {($i+10)*100}] 177*4c68e6d2Sdrh lappend list $lwr $upr 178*4c68e6d2Sdrh} 179*4c68e6d2Sdrhset script { 180*4c68e6d2Sdrh foreach {lwr upr} $::list { 181*4c68e6d2Sdrh db eval {SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr} 182*4c68e6d2Sdrh } 183*4c68e6d2Sdrh} 184*4c68e6d2Sdrhexplain {SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr} 185*4c68e6d2Sdrhdb eval BEGIN 186*4c68e6d2Sdrhspeed_trial_tcl speed1p-select3 5000 stmt $script 187*4c68e6d2Sdrhdb eval COMMIT 188*4c68e6d2Sdrh 189*4c68e6d2Sdrh# 100000 random SELECTs against rowid. 190*4c68e6d2Sdrh# 191*4c68e6d2Sdrhset list {} 192*4c68e6d2Sdrhfor {set i 1} {$i<=100000} {incr i} { 193*4c68e6d2Sdrh set id [expr {int(rand()*50000)+1}] 194*4c68e6d2Sdrh lappend list $id 195*4c68e6d2Sdrh} 196*4c68e6d2Sdrhset script { 197*4c68e6d2Sdrh foreach id $::list { 198*4c68e6d2Sdrh db eval {SELECT c FROM t1 WHERE rowid=$id} 199*4c68e6d2Sdrh } 200*4c68e6d2Sdrh} 201*4c68e6d2Sdrhexplain {SELECT c FROM t1 WHERE rowid=$id} 202*4c68e6d2Sdrhdb eval BEGIN 203*4c68e6d2Sdrhspeed_trial_tcl speed1p-select4 100000 row $script 204*4c68e6d2Sdrhdb eval COMMIT 205*4c68e6d2Sdrh 206*4c68e6d2Sdrh# 100000 random SELECTs against a unique indexed column. 207*4c68e6d2Sdrh# 208*4c68e6d2Sdrhset list {} 209*4c68e6d2Sdrhfor {set i 1} {$i<=100000} {incr i} { 210*4c68e6d2Sdrh set id [expr {int(rand()*50000)+1}] 211*4c68e6d2Sdrh lappend list $id 212*4c68e6d2Sdrh} 213*4c68e6d2Sdrhset script { 214*4c68e6d2Sdrh foreach id $::list { 215*4c68e6d2Sdrh db eval {SELECT c FROM t1 WHERE a=$id} 216*4c68e6d2Sdrh } 217*4c68e6d2Sdrh} 218*4c68e6d2Sdrhexplain {SELECT c FROM t1 WHERE a=$id} 219*4c68e6d2Sdrhdb eval BEGIN 220*4c68e6d2Sdrhspeed_trial_tcl speed1p-select5 100000 row $script 221*4c68e6d2Sdrhdb eval COMMIT 222*4c68e6d2Sdrh 223*4c68e6d2Sdrh# 50000 random SELECTs against an indexed column text column 224*4c68e6d2Sdrh# 225*4c68e6d2Sdrhset list [db eval {SELECT c FROM t1 ORDER BY random() LIMIT 50000}] 226*4c68e6d2Sdrhset script { 227*4c68e6d2Sdrh foreach c $::list { 228*4c68e6d2Sdrh db eval {SELECT c FROM t1 WHERE c=$c} 229*4c68e6d2Sdrh } 230*4c68e6d2Sdrh} 231*4c68e6d2Sdrhexplain {SELECT c FROM t1 WHERE c=$c} 232*4c68e6d2Sdrhdb eval BEGIN 233*4c68e6d2Sdrhspeed_trial_tcl speed1p-select6 50000 row $script 234*4c68e6d2Sdrhdb eval COMMIT 235*4c68e6d2Sdrh 236*4c68e6d2Sdrh 237*4c68e6d2Sdrh# Vacuum 238*4c68e6d2Sdrhspeed_trial speed1p-vacuum 100000 row VACUUM 239*4c68e6d2Sdrh 240*4c68e6d2Sdrh# 5000 updates of ranges where the field being compared is indexed. 241*4c68e6d2Sdrh# 242*4c68e6d2Sdrhset list {} 243*4c68e6d2Sdrhfor {set i 0} {$i<5000} {incr i} { 244*4c68e6d2Sdrh set lwr [expr {$i*2}] 245*4c68e6d2Sdrh set upr [expr {($i+1)*2}] 246*4c68e6d2Sdrh lappend list $lwr $upr 247*4c68e6d2Sdrh} 248*4c68e6d2Sdrhset script { 249*4c68e6d2Sdrh foreach {lwr upr} $::list { 250*4c68e6d2Sdrh db eval {UPDATE t1 SET b=b*2 WHERE a>=$lwr AND a<$upr} 251*4c68e6d2Sdrh } 252*4c68e6d2Sdrh} 253*4c68e6d2Sdrhexplain {UPDATE t1 SET b=b*2 WHERE a>=$lwr AND a<$upr} 254*4c68e6d2Sdrhdb eval BEGIN 255*4c68e6d2Sdrhspeed_trial_tcl speed1p-update1 5000 stmt $script 256*4c68e6d2Sdrhdb eval COMMIT 257*4c68e6d2Sdrh 258*4c68e6d2Sdrh# 50000 single-row updates. An index is used to find the row quickly. 259*4c68e6d2Sdrh# 260*4c68e6d2Sdrhset list {} 261*4c68e6d2Sdrhfor {set i 0} {$i<50000} {incr i} { 262*4c68e6d2Sdrh set r [expr {int(rand()*500000)}] 263*4c68e6d2Sdrh lappend list $i $r 264*4c68e6d2Sdrh} 265*4c68e6d2Sdrhset script { 266*4c68e6d2Sdrh foreach {i r} $::list { 267*4c68e6d2Sdrh db eval {UPDATE t1 SET b=$r WHERE a=$i} 268*4c68e6d2Sdrh } 269*4c68e6d2Sdrh} 270*4c68e6d2Sdrhexplain {UPDATE t1 SET b=$r WHERE a=$i} 271*4c68e6d2Sdrhdb eval BEGIN 272*4c68e6d2Sdrhspeed_trial_tcl speed1p-update2 50000 row $script 273*4c68e6d2Sdrhdb eval COMMIT 274*4c68e6d2Sdrh 275*4c68e6d2Sdrh# 1 big text update that touches every row in the table. 276*4c68e6d2Sdrh# 277*4c68e6d2Sdrhexplain {UPDATE t1 SET c=a} 278*4c68e6d2Sdrhspeed_trial speed1p-update3 50000 row { 279*4c68e6d2Sdrh UPDATE t1 SET c=a; 280*4c68e6d2Sdrh} 281*4c68e6d2Sdrh 282*4c68e6d2Sdrh# Many individual text updates. Each row in the table is 283*4c68e6d2Sdrh# touched through an index. 284*4c68e6d2Sdrh# 285*4c68e6d2Sdrhset list {} 286*4c68e6d2Sdrhfor {set i 1} {$i<=50000} {incr i} { 287*4c68e6d2Sdrh set r [expr {int(rand()*500000)}] 288*4c68e6d2Sdrh lappend list $i [number_name $r] 289*4c68e6d2Sdrh} 290*4c68e6d2Sdrhset script { 291*4c68e6d2Sdrh foreach {i x} $::list { 292*4c68e6d2Sdrh db eval {UPDATE t1 SET c=$x WHERE a=$i} 293*4c68e6d2Sdrh } 294*4c68e6d2Sdrh} 295*4c68e6d2Sdrhexplain {UPDATE t1 SET c=$x WHERE a=$i} 296*4c68e6d2Sdrhdb eval BEGIN 297*4c68e6d2Sdrhspeed_trial_tcl speed1p-update4 50000 row $script 298*4c68e6d2Sdrhdb eval COMMIT 299*4c68e6d2Sdrh 300*4c68e6d2Sdrh# Delete all content in a table. 301*4c68e6d2Sdrh# 302*4c68e6d2Sdrhexplain {DELETE FROM t1} 303*4c68e6d2Sdrhspeed_trial speed1p-delete1 50000 row {DELETE FROM t1} 304*4c68e6d2Sdrh 305*4c68e6d2Sdrh# Copy one table into another 306*4c68e6d2Sdrh# 307*4c68e6d2Sdrhexplain {INSERT INTO t1 SELECT * FROM t2} 308*4c68e6d2Sdrhspeed_trial speed1p-copy1 50000 row {INSERT INTO t1 SELECT * FROM t2} 309*4c68e6d2Sdrh 310*4c68e6d2Sdrh# Delete all content in a table, one row at a time. 311*4c68e6d2Sdrh# 312*4c68e6d2Sdrhexplain {DELETE FROM t1 WHERE 1} 313*4c68e6d2Sdrhspeed_trial speed1p-delete2 50000 row {DELETE FROM t1 WHERE 1} 314*4c68e6d2Sdrh 315*4c68e6d2Sdrh# Refill the table yet again 316*4c68e6d2Sdrh# 317*4c68e6d2Sdrhspeed_trial speed1p-copy2 50000 row {INSERT INTO t1 SELECT * FROM t2} 318*4c68e6d2Sdrh 319*4c68e6d2Sdrh# Drop the table and recreate it without its indices. 320*4c68e6d2Sdrh# 321*4c68e6d2Sdrhexplain {DROP TABLE t1} 322*4c68e6d2Sdrhexplain {CREATE TABLE tX(a INTEGER, b INTEGER, c TEXT)} 323*4c68e6d2Sdrhdb eval BEGIN 324*4c68e6d2Sdrhspeed_trial speed1p-drop1 50000 row { 325*4c68e6d2Sdrh DROP TABLE t1; 326*4c68e6d2Sdrh CREATE TABLE t1(a INTEGER, b INTEGER, c TEXT); 327*4c68e6d2Sdrh} 328*4c68e6d2Sdrhdb eval COMMIT 329*4c68e6d2Sdrh 330*4c68e6d2Sdrh# Refill the table yet again. This copy should be faster because 331*4c68e6d2Sdrh# there are no indices to deal with. 332*4c68e6d2Sdrh# 333*4c68e6d2Sdrhspeed_trial speed1p-copy3 50000 row {INSERT INTO t1 SELECT * FROM t2} 334*4c68e6d2Sdrh 335*4c68e6d2Sdrh# Select 20000 rows from the table at random. 336*4c68e6d2Sdrh# 337*4c68e6d2Sdrhexplain {SELECT rowid FROM t1 ORDER BY random() LIMIT 20000} 338*4c68e6d2Sdrhspeed_trial speed1p-random1 50000 row { 339*4c68e6d2Sdrh SELECT rowid FROM t1 ORDER BY random() LIMIT 20000 340*4c68e6d2Sdrh} 341*4c68e6d2Sdrh 342*4c68e6d2Sdrh# Delete 20000 random rows from the table. 343*4c68e6d2Sdrh# 344*4c68e6d2Sdrhexplain {DELETE FROM t1 WHERE rowid IN 345*4c68e6d2Sdrh (SELECT rowid FROM t1 ORDER BY random() LIMIT 20000)} 346*4c68e6d2Sdrhspeed_trial speed1p-random-del1 20000 row { 347*4c68e6d2Sdrh DELETE FROM t1 WHERE rowid IN 348*4c68e6d2Sdrh (SELECT rowid FROM t1 ORDER BY random() LIMIT 20000) 349*4c68e6d2Sdrh} 350*4c68e6d2Sdrhdo_test speed1p-1.1 { 351*4c68e6d2Sdrh db one {SELECT count(*) FROM t1} 352*4c68e6d2Sdrh} 30000 353*4c68e6d2Sdrh 354*4c68e6d2Sdrh 355*4c68e6d2Sdrh# Delete 20000 more rows at random from the table. 356*4c68e6d2Sdrh# 357*4c68e6d2Sdrhspeed_trial speed1p-random-del2 20000 row { 358*4c68e6d2Sdrh DELETE FROM t1 WHERE rowid IN 359*4c68e6d2Sdrh (SELECT rowid FROM t1 ORDER BY random() LIMIT 20000) 360*4c68e6d2Sdrh} 361*4c68e6d2Sdrhdo_test speed1p-1.2 { 362*4c68e6d2Sdrh db one {SELECT count(*) FROM t1} 363*4c68e6d2Sdrh} 10000 364*4c68e6d2Sdrhspeed_trial_summary speed1 365*4c68e6d2Sdrh 366*4c68e6d2Sdrhfinish_test 367