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