1# 2006 November 23 2# 3# The author disclaims copyright to this source code. In place of 4# a legal notice, here is a blessing: 5# 6# May you do good and not evil. 7# May you find forgiveness for yourself and forgive others. 8# May you share freely, never taking more than you give. 9# 10#************************************************************************* 11# This file implements regression tests for SQLite library. The 12# focus of this script is measuring executing speed. 13# 14# $Id: speed1.test,v 1.1 2006/11/29 20:53:00 drh Exp $ 15# 16 17set testdir [file dirname $argv0] 18source $testdir/tester.tcl 19 20# The number_name procedure below converts its argment (an integer) 21# into a string which is the English-language name for that number. 22# 23# Example: 24# 25# puts [number_name 123] -> "one hundred twenty three" 26# 27set ones {zero one two three four five six seven eight nine 28 ten eleven twelve thirteen fourteen fifteen sixteen seventeen 29 eighteen nineteen} 30set tens {{} ten twenty thirty forty fifty sixty seventy eighty ninety} 31proc number_name {n} { 32 if {$n>=1000} { 33 set txt "[number_name [expr {$n/1000}]] thousand" 34 set n [expr {$n%1000}] 35 } else { 36 set txt {} 37 } 38 if {$n>=100} { 39 append txt " [lindex $::ones [expr {$n/100}]] hundred" 40 set n [expr {$n%100}] 41 } 42 if {$n>=20} { 43 append txt " [lindex $::tens [expr {$n/10}]]" 44 set n [expr {$n%10}] 45 } 46 if {$n>0} { 47 append txt " [lindex $::ones $n]" 48 } 49 set txt [string trim $txt] 50 if {$txt==""} {set txt zero} 51 return $txt 52} 53 54# Create a database schema. 55# 56do_test speed1-1.0 { 57 execsql { 58 CREATE TABLE t1(a INTEGER, b INTEGER, c TEXT); 59 CREATE TABLE t2(a INTEGER, b INTEGER, c TEXT); 60 CREATE INDEX i2a ON t2(a); 61 CREATE INDEX i2b ON t2(b); 62 SELECT name FROM sqlite_master ORDER BY 1; 63 } 64} {i2a i2b t1 t2} 65 66 67# 50000 INSERTs on an unindexed table 68# 69set sql {} 70for {set i 1} {$i<=50000} {incr i} { 71 set r [expr {int(rand()*500000)}] 72 append sql "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');\n" 73} 74db eval BEGIN 75speed_trial speed1-insert1 50000 row $sql 76db eval COMMIT 77 78# 50000 INSERTs on an indexed table 79# 80set sql {} 81for {set i 1} {$i<=50000} {incr i} { 82 set r [expr {int(rand()*500000)}] 83 append sql "INSERT INTO t2 VALUES($i,$r,'[number_name $r]');\n" 84} 85db eval BEGIN 86speed_trial speed1-insert2 50000 row $sql 87db eval COMMIT 88 89 90 91# 50 SELECTs on an integer comparison. There is no index so 92# a full table scan is required. 93# 94set sql {} 95for {set i 0} {$i<50} {incr i} { 96 set lwr [expr {$i*100}] 97 set upr [expr {($i+10)*100}] 98 append sql "SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr;" 99} 100db eval BEGIN 101speed_trial speed1-select1 [expr {50*50000}] row $sql 102db eval COMMIT 103 104# 50 SELECTs on an LIKE comparison. There is no index so a full 105# table scan is required. 106# 107set sql {} 108for {set i 0} {$i<50} {incr i} { 109 append sql \ 110 "SELECT count(*), avg(b) FROM t1 WHERE c LIKE '%[number_name $i]%';" 111} 112db eval BEGIN 113speed_trial speed1-select2 [expr {50*50000}] row $sql 114db eval COMMIT 115 116# Create indices 117# 118db eval BEGIN 119speed_trial speed1-createidx 150000 row { 120 CREATE INDEX i1a ON t1(a); 121 CREATE INDEX i1b ON t1(b); 122 CREATE INDEX i1c ON t1(c); 123} 124db eval COMMIT 125 126# 5000 SELECTs on an integer comparison where the integer is 127# indexed. 128# 129set sql {} 130for {set i 0} {$i<5000} {incr i} { 131 set lwr [expr {$i*100}] 132 set upr [expr {($i+10)*100}] 133 append sql "SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr;" 134} 135db eval BEGIN 136speed_trial speed1-select3 5000 stmt $sql 137db eval COMMIT 138 139# 20000 random SELECTs against rowid. 140# 141set sql {} 142for {set i 1} {$i<=20000} {incr i} { 143 set id [expr {int(rand()*50000)+1}] 144 append sql "SELECT c FROM t1 WHERE rowid=$id;" 145} 146db eval BEGIN 147speed_trial speed1-select4 20000 row $sql 148db eval COMMIT 149 150# 20000 random SELECTs against a unique indexed column. 151# 152set sql {} 153for {set i 1} {$i<=20000} {incr i} { 154 set id [expr {int(rand()*50000)+1}] 155 append sql "SELECT c FROM t1 WHERE a=$id;" 156} 157db eval BEGIN 158speed_trial speed1-select5 20000 row $sql 159db eval COMMIT 160 161# 20000 random SELECTs against an indexed column text column 162# 163set sql {} 164db eval {SELECT c FROM t1 ORDER BY random() LIMIT 20000} { 165 append sql "SELECT c FROM t1 WHERE c='$c';" 166} 167db eval BEGIN 168speed_trial speed1-select6 20000 row $sql 169db eval COMMIT 170 171 172# Vacuum 173speed_trial speed1-vacuum 100000 row VACUUM 174 175# 5000 updates of ranges where the field being compared is indexed. 176# 177set sql {} 178for {set i 0} {$i<5000} {incr i} { 179 set lwr [expr {$i*2}] 180 set upr [expr {($i+1)*2}] 181 append sql "UPDATE t1 SET b=b*2 WHERE a>=$lwr AND a<$upr;" 182} 183db eval BEGIN 184speed_trial speed1-update1 5000 stmt $sql 185db eval COMMIT 186 187# 50000 single-row updates. An index is used to find the row quickly. 188# 189set sql {} 190for {set i 0} {$i<50000} {incr i} { 191 set r [expr {int(rand()*500000)}] 192 append sql "UPDATE t1 SET b=$r WHERE a=$i;" 193} 194db eval BEGIN 195speed_trial speed1-update2 50000 row $sql 196db eval COMMIT 197 198# 1 big text update that touches every row in the table. 199# 200speed_trial speed1-update3 50000 row { 201 UPDATE t1 SET c=a; 202} 203 204# Many individual text updates. Each row in the table is 205# touched through an index. 206# 207set sql {} 208for {set i 1} {$i<=50000} {incr i} { 209 set r [expr {int(rand()*500000)}] 210 append sql "UPDATE t1 SET c='[number_name $r]' WHERE a=$i;" 211} 212db eval BEGIN 213speed_trial speed1-update4 50000 row $sql 214db eval COMMIT 215 216# Delete all content in a table. 217# 218speed_trial speed1-delete1 50000 row {DELETE FROM t1} 219 220# Copy one table into another 221# 222speed_trial speed1-copy1 50000 row {INSERT INTO t1 SELECT * FROM t2} 223 224# Delete all content in a table, one row at a time. 225# 226speed_trial speed1-delete2 50000 row {DELETE FROM t1 WHERE 1} 227 228# Refill the table yet again 229# 230speed_trial speed1-copy2 50000 row {INSERT INTO t1 SELECT * FROM t2} 231 232# Drop the table and recreate it without its indices. 233# 234db eval BEGIN 235speed_trial speed1-drop1 50000 row { 236 DROP TABLE t1; 237 CREATE TABLE t1(a INTEGER, b INTEGER, c TEXT); 238} 239db eval COMMIT 240 241# Refill the table yet again. This copy should be faster because 242# there are no indices to deal with. 243# 244speed_trial speed1-copy3 50000 row {INSERT INTO t1 SELECT * FROM t2} 245 246# Select 20000 rows from the table at random. 247# 248speed_trial speed1-random1 50000 row { 249 SELECT rowid FROM t1 ORDER BY random() LIMIT 20000 250} 251 252# Delete 20000 random rows from the table. 253# 254speed_trial speed1-random-del1 20000 row { 255 DELETE FROM t1 WHERE rowid IN 256 (SELECT rowid FROM t1 ORDER BY random() LIMIT 20000) 257} 258do_test speed1-1.1 { 259 db one {SELECT count(*) FROM t1} 260} 30000 261 262 263# Delete 20000 more rows at random from the table. 264# 265speed_trial speed1-random-del2 20000 row { 266 DELETE FROM t1 WHERE rowid IN 267 (SELECT rowid FROM t1 ORDER BY random() LIMIT 20000) 268} 269do_test speed1-1.2 { 270 db one {SELECT count(*) FROM t1} 271} 10000 272 273finish_test 274