1e4dd73b4Sdrh# 2006 November 23 2e4dd73b4Sdrh# 3e4dd73b4Sdrh# The author disclaims copyright to this source code. In place of 4e4dd73b4Sdrh# a legal notice, here is a blessing: 5e4dd73b4Sdrh# 6e4dd73b4Sdrh# May you do good and not evil. 7e4dd73b4Sdrh# May you find forgiveness for yourself and forgive others. 8e4dd73b4Sdrh# May you share freely, never taking more than you give. 9e4dd73b4Sdrh# 10e4dd73b4Sdrh#************************************************************************* 11e4dd73b4Sdrh# This file implements regression tests for SQLite library. The 12e4dd73b4Sdrh# focus of this script is measuring executing speed. 13e4dd73b4Sdrh# 14*86a88114Sdrh# $Id: speed2.test,v 1.7 2007/04/16 15:02:20 drh Exp $ 15e4dd73b4Sdrh# 16e4dd73b4Sdrh 17e4dd73b4Sdrhset testdir [file dirname $argv0] 18e4dd73b4Sdrhsource $testdir/tester.tcl 19dd92431aSdrhspeed_trial_init speed2 20e4dd73b4Sdrh 2145068f4bSdrh# Set a uniform random seed 2245068f4bSdrhexpr srand(0) 2345068f4bSdrh 2491c58e23Sdrhset sqlout [open speed2.txt w] 25e4dd73b4Sdrhproc tracesql {sql} { 26e4dd73b4Sdrh puts $::sqlout $sql\; 27e4dd73b4Sdrh} 28e4dd73b4Sdrh#db trace tracesql 29e4dd73b4Sdrh 30e4dd73b4Sdrh# The number_name procedure below converts its argment (an integer) 31e4dd73b4Sdrh# into a string which is the English-language name for that number. 32e4dd73b4Sdrh# 33e4dd73b4Sdrh# Example: 34e4dd73b4Sdrh# 35e4dd73b4Sdrh# puts [number_name 123] -> "one hundred twenty three" 36e4dd73b4Sdrh# 37e4dd73b4Sdrhset ones {zero one two three four five six seven eight nine 38e4dd73b4Sdrh ten eleven twelve thirteen fourteen fifteen sixteen seventeen 39e4dd73b4Sdrh eighteen nineteen} 40e4dd73b4Sdrhset tens {{} ten twenty thirty forty fifty sixty seventy eighty ninety} 41e4dd73b4Sdrhproc number_name {n} { 42e4dd73b4Sdrh if {$n>=1000} { 43e4dd73b4Sdrh set txt "[number_name [expr {$n/1000}]] thousand" 44e4dd73b4Sdrh set n [expr {$n%1000}] 45e4dd73b4Sdrh } else { 46e4dd73b4Sdrh set txt {} 47e4dd73b4Sdrh } 48e4dd73b4Sdrh if {$n>=100} { 49e4dd73b4Sdrh append txt " [lindex $::ones [expr {$n/100}]] hundred" 50e4dd73b4Sdrh set n [expr {$n%100}] 51e4dd73b4Sdrh } 52e4dd73b4Sdrh if {$n>=20} { 53e4dd73b4Sdrh append txt " [lindex $::tens [expr {$n/10}]]" 54e4dd73b4Sdrh set n [expr {$n%10}] 55e4dd73b4Sdrh } 56e4dd73b4Sdrh if {$n>0} { 57e4dd73b4Sdrh append txt " [lindex $::ones $n]" 58e4dd73b4Sdrh } 59e4dd73b4Sdrh set txt [string trim $txt] 60e4dd73b4Sdrh if {$txt==""} {set txt zero} 61e4dd73b4Sdrh return $txt 62e4dd73b4Sdrh} 63e4dd73b4Sdrh 64e4dd73b4Sdrh# Create a database schema. 65e4dd73b4Sdrh# 6691c58e23Sdrhdo_test speed2-1.0 { 67e4dd73b4Sdrh execsql { 68e4dd73b4Sdrh PRAGMA page_size=1024; 69e4dd73b4Sdrh PRAGMA cache_size=8192; 70*86a88114Sdrh PRAGMA locking_mode=EXCLUSIVE; 71e4dd73b4Sdrh CREATE TABLE t1(a INTEGER, b INTEGER, c TEXT); 72e4dd73b4Sdrh CREATE TABLE t2(a INTEGER, b INTEGER, c TEXT); 73e4dd73b4Sdrh CREATE INDEX i2a ON t2(a); 74e4dd73b4Sdrh CREATE INDEX i2b ON t2(b); 75e4dd73b4Sdrh } 76e4dd73b4Sdrh execsql { 77e4dd73b4Sdrh SELECT name FROM sqlite_master ORDER BY 1; 78e4dd73b4Sdrh } 79e4dd73b4Sdrh} {i2a i2b t1 t2} 80e4dd73b4Sdrh 81e4dd73b4Sdrh 82e4dd73b4Sdrh# 50000 INSERTs on an unindexed table 83e4dd73b4Sdrh# 84e4dd73b4Sdrhset sql {} 85e4dd73b4Sdrhfor {set i 1} {$i<=50000} {incr i} { 86e4dd73b4Sdrh set r [expr {int(rand()*500000)}] 87e4dd73b4Sdrh append sql "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');\n" 88e4dd73b4Sdrh} 89e4dd73b4Sdrhdb eval BEGIN 9091c58e23Sdrhspeed_trial speed2-insert1 50000 row $sql 91e4dd73b4Sdrhdb eval COMMIT 92e4dd73b4Sdrh 93e4dd73b4Sdrh# 50000 INSERTs on an indexed table 94e4dd73b4Sdrh# 95e4dd73b4Sdrhset sql {} 96e4dd73b4Sdrhfor {set i 1} {$i<=50000} {incr i} { 97e4dd73b4Sdrh set r [expr {int(rand()*500000)}] 98e4dd73b4Sdrh append sql "INSERT INTO t2 VALUES($i,$r,'[number_name $r]');\n" 99e4dd73b4Sdrh} 100e4dd73b4Sdrhdb eval BEGIN 10191c58e23Sdrhspeed_trial speed2-insert2 50000 row $sql 102e4dd73b4Sdrhdb eval COMMIT 103e4dd73b4Sdrh 104e4dd73b4Sdrh 105e4dd73b4Sdrh 106e4dd73b4Sdrh# 50 SELECTs on an integer comparison. There is no index so 107e4dd73b4Sdrh# a full table scan is required. 108e4dd73b4Sdrh# 109e4dd73b4Sdrhset sql {} 110e4dd73b4Sdrhfor {set i 0} {$i<50} {incr i} { 111e4dd73b4Sdrh set lwr [expr {$i*100}] 112e4dd73b4Sdrh set upr [expr {($i+10)*100}] 113e4dd73b4Sdrh append sql "SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr;" 114e4dd73b4Sdrh} 11595bad4c7Sdrhspeed_trial speed2-select1a [expr {50*50000}] row $sql 116e4dd73b4Sdrh 117e4dd73b4Sdrh# 50 SELECTs on an LIKE comparison. There is no index so a full 118e4dd73b4Sdrh# table scan is required. 119e4dd73b4Sdrh# 120e4dd73b4Sdrhset sql {} 121e4dd73b4Sdrhfor {set i 0} {$i<50} {incr i} { 122e4dd73b4Sdrh append sql \ 123e4dd73b4Sdrh "SELECT count(*), avg(b) FROM t1 WHERE c LIKE '%[number_name $i]%';" 124e4dd73b4Sdrh} 12595bad4c7Sdrhspeed_trial speed2-select2a [expr {50*50000}] row $sql 12695bad4c7Sdrh 12795bad4c7Sdrh# Vacuum 12895bad4c7Sdrhspeed_trial speed2-vacuum1 100000 row VACUUM 12995bad4c7Sdrh 13095bad4c7Sdrh# 50 SELECTs on an integer comparison. There is no index so 13195bad4c7Sdrh# a full table scan is required. 13295bad4c7Sdrh# 13395bad4c7Sdrhset sql {} 13495bad4c7Sdrhfor {set i 0} {$i<50} {incr i} { 13595bad4c7Sdrh set lwr [expr {$i*100}] 13695bad4c7Sdrh set upr [expr {($i+10)*100}] 13795bad4c7Sdrh append sql "SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr;" 13895bad4c7Sdrh} 13995bad4c7Sdrhspeed_trial speed2-select1b [expr {50*50000}] row $sql 14095bad4c7Sdrh 14195bad4c7Sdrh# 50 SELECTs on an LIKE comparison. There is no index so a full 14295bad4c7Sdrh# table scan is required. 14395bad4c7Sdrh# 14495bad4c7Sdrhset sql {} 14595bad4c7Sdrhfor {set i 0} {$i<50} {incr i} { 14695bad4c7Sdrh append sql \ 14795bad4c7Sdrh "SELECT count(*), avg(b) FROM t1 WHERE c LIKE '%[number_name $i]%';" 14895bad4c7Sdrh} 14995bad4c7Sdrhspeed_trial speed2-select2b [expr {50*50000}] row $sql 150e4dd73b4Sdrh 151e4dd73b4Sdrh# Create indices 152e4dd73b4Sdrh# 153e4dd73b4Sdrhdb eval BEGIN 15491c58e23Sdrhspeed_trial speed2-createidx 150000 row { 155e4dd73b4Sdrh CREATE INDEX i1a ON t1(a); 156e4dd73b4Sdrh CREATE INDEX i1b ON t1(b); 157e4dd73b4Sdrh CREATE INDEX i1c ON t1(c); 158e4dd73b4Sdrh} 159e4dd73b4Sdrhdb eval COMMIT 160e4dd73b4Sdrh 161e4dd73b4Sdrh# 5000 SELECTs on an integer comparison where the integer is 162e4dd73b4Sdrh# indexed. 163e4dd73b4Sdrh# 164e4dd73b4Sdrhset sql {} 165e4dd73b4Sdrhfor {set i 0} {$i<5000} {incr i} { 166e4dd73b4Sdrh set lwr [expr {$i*100}] 167e4dd73b4Sdrh set upr [expr {($i+10)*100}] 168e4dd73b4Sdrh append sql "SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr;" 169e4dd73b4Sdrh} 17095bad4c7Sdrhspeed_trial speed2-select3a 5000 stmt $sql 171e4dd73b4Sdrh 172e4dd73b4Sdrh# 100000 random SELECTs against rowid. 173e4dd73b4Sdrh# 174e4dd73b4Sdrhset sql {} 175e4dd73b4Sdrhfor {set i 1} {$i<=100000} {incr i} { 176e4dd73b4Sdrh set id [expr {int(rand()*50000)+1}] 177e4dd73b4Sdrh append sql "SELECT c=='hi' FROM t1 WHERE rowid=$id;\n" 178e4dd73b4Sdrh} 17995bad4c7Sdrhspeed_trial speed2-select4a 100000 row $sql 180e4dd73b4Sdrh 181e4dd73b4Sdrh# 100000 random SELECTs against a unique indexed column. 182e4dd73b4Sdrh# 183e4dd73b4Sdrhset sql {} 184e4dd73b4Sdrhfor {set i 1} {$i<=100000} {incr i} { 185e4dd73b4Sdrh set id [expr {int(rand()*50000)+1}] 186e4dd73b4Sdrh append sql "SELECT c FROM t1 WHERE a=$id;" 187e4dd73b4Sdrh} 18895bad4c7Sdrhspeed_trial speed2-select5a 100000 row $sql 189e4dd73b4Sdrh 190e4dd73b4Sdrh# 50000 random SELECTs against an indexed column text column 191e4dd73b4Sdrh# 192e4dd73b4Sdrhset sql {} 193e4dd73b4Sdrhdb eval {SELECT c FROM t1 ORDER BY random() LIMIT 50000} { 194e4dd73b4Sdrh append sql "SELECT c FROM t1 WHERE c='$c';" 195e4dd73b4Sdrh} 19695bad4c7Sdrhspeed_trial speed2-select6a 50000 row $sql 197e4dd73b4Sdrh 198e4dd73b4Sdrh# Vacuum 19995bad4c7Sdrhspeed_trial speed2-vacuum2 100000 row VACUUM 20095bad4c7Sdrh 20195bad4c7Sdrh 20295bad4c7Sdrh# 5000 SELECTs on an integer comparison where the integer is 20395bad4c7Sdrh# indexed. 20495bad4c7Sdrh# 20595bad4c7Sdrhset sql {} 20695bad4c7Sdrhfor {set i 0} {$i<5000} {incr i} { 20795bad4c7Sdrh set lwr [expr {$i*100}] 20895bad4c7Sdrh set upr [expr {($i+10)*100}] 20995bad4c7Sdrh append sql "SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr;" 21095bad4c7Sdrh} 21195bad4c7Sdrhspeed_trial speed2-select3b 5000 stmt $sql 21295bad4c7Sdrh 21395bad4c7Sdrh# 100000 random SELECTs against rowid. 21495bad4c7Sdrh# 21595bad4c7Sdrhset sql {} 21695bad4c7Sdrhfor {set i 1} {$i<=100000} {incr i} { 21795bad4c7Sdrh set id [expr {int(rand()*50000)+1}] 21895bad4c7Sdrh append sql "SELECT c=='hi' FROM t1 WHERE rowid=$id;\n" 21995bad4c7Sdrh} 22095bad4c7Sdrhspeed_trial speed2-select4b 100000 row $sql 22195bad4c7Sdrh 22295bad4c7Sdrh# 100000 random SELECTs against a unique indexed column. 22395bad4c7Sdrh# 22495bad4c7Sdrhset sql {} 22595bad4c7Sdrhfor {set i 1} {$i<=100000} {incr i} { 22695bad4c7Sdrh set id [expr {int(rand()*50000)+1}] 22795bad4c7Sdrh append sql "SELECT c FROM t1 WHERE a=$id;" 22895bad4c7Sdrh} 22995bad4c7Sdrhspeed_trial speed2-select5b 100000 row $sql 23095bad4c7Sdrh 23195bad4c7Sdrh# 50000 random SELECTs against an indexed column text column 23295bad4c7Sdrh# 23395bad4c7Sdrhset sql {} 23495bad4c7Sdrhdb eval {SELECT c FROM t1 ORDER BY random() LIMIT 50000} { 23595bad4c7Sdrh append sql "SELECT c FROM t1 WHERE c='$c';" 23695bad4c7Sdrh} 23795bad4c7Sdrhspeed_trial speed2-select6b 50000 row $sql 238e4dd73b4Sdrh 239e4dd73b4Sdrh# 5000 updates of ranges where the field being compared is indexed. 240e4dd73b4Sdrh# 241e4dd73b4Sdrhset sql {} 242e4dd73b4Sdrhfor {set i 0} {$i<5000} {incr i} { 243e4dd73b4Sdrh set lwr [expr {$i*2}] 244e4dd73b4Sdrh set upr [expr {($i+1)*2}] 245e4dd73b4Sdrh append sql "UPDATE t1 SET b=b*2 WHERE a>=$lwr AND a<$upr;" 246e4dd73b4Sdrh} 247e4dd73b4Sdrhdb eval BEGIN 24891c58e23Sdrhspeed_trial speed2-update1 5000 stmt $sql 249e4dd73b4Sdrhdb eval COMMIT 250e4dd73b4Sdrh 251e4dd73b4Sdrh# 50000 single-row updates. An index is used to find the row quickly. 252e4dd73b4Sdrh# 253e4dd73b4Sdrhset sql {} 254e4dd73b4Sdrhfor {set i 0} {$i<50000} {incr i} { 255e4dd73b4Sdrh set r [expr {int(rand()*500000)}] 256e4dd73b4Sdrh append sql "UPDATE t1 SET b=$r WHERE a=$i;" 257e4dd73b4Sdrh} 258e4dd73b4Sdrhdb eval BEGIN 25991c58e23Sdrhspeed_trial speed2-update2 50000 row $sql 260e4dd73b4Sdrhdb eval COMMIT 261e4dd73b4Sdrh 262e4dd73b4Sdrh# 1 big text update that touches every row in the table. 263e4dd73b4Sdrh# 26491c58e23Sdrhspeed_trial speed2-update3 50000 row { 265e4dd73b4Sdrh UPDATE t1 SET c=a; 266e4dd73b4Sdrh} 267e4dd73b4Sdrh 268e4dd73b4Sdrh# Many individual text updates. Each row in the table is 269e4dd73b4Sdrh# touched through an index. 270e4dd73b4Sdrh# 271e4dd73b4Sdrhset sql {} 272e4dd73b4Sdrhfor {set i 1} {$i<=50000} {incr i} { 273e4dd73b4Sdrh set r [expr {int(rand()*500000)}] 274e4dd73b4Sdrh append sql "UPDATE t1 SET c='[number_name $r]' WHERE a=$i;" 275e4dd73b4Sdrh} 276e4dd73b4Sdrhdb eval BEGIN 27791c58e23Sdrhspeed_trial speed2-update4 50000 row $sql 278e4dd73b4Sdrhdb eval COMMIT 279e4dd73b4Sdrh 280e4dd73b4Sdrh# Delete all content in a table. 281e4dd73b4Sdrh# 28291c58e23Sdrhspeed_trial speed2-delete1 50000 row {DELETE FROM t1} 283e4dd73b4Sdrh 284e4dd73b4Sdrh# Copy one table into another 285e4dd73b4Sdrh# 28691c58e23Sdrhspeed_trial speed2-copy1 50000 row {INSERT INTO t1 SELECT * FROM t2} 287e4dd73b4Sdrh 288e4dd73b4Sdrh# Delete all content in a table, one row at a time. 289e4dd73b4Sdrh# 29091c58e23Sdrhspeed_trial speed2-delete2 50000 row {DELETE FROM t1 WHERE 1} 291e4dd73b4Sdrh 292e4dd73b4Sdrh# Refill the table yet again 293e4dd73b4Sdrh# 29491c58e23Sdrhspeed_trial speed2-copy2 50000 row {INSERT INTO t1 SELECT * FROM t2} 295e4dd73b4Sdrh 296e4dd73b4Sdrh# Drop the table and recreate it without its indices. 297e4dd73b4Sdrh# 298e4dd73b4Sdrhdb eval BEGIN 29991c58e23Sdrhspeed_trial speed2-drop1 50000 row { 300e4dd73b4Sdrh DROP TABLE t1; 301e4dd73b4Sdrh CREATE TABLE t1(a INTEGER, b INTEGER, c TEXT); 302e4dd73b4Sdrh} 303e4dd73b4Sdrhdb eval COMMIT 304e4dd73b4Sdrh 305e4dd73b4Sdrh# Refill the table yet again. This copy should be faster because 306e4dd73b4Sdrh# there are no indices to deal with. 307e4dd73b4Sdrh# 30891c58e23Sdrhspeed_trial speed2-copy3 50000 row {INSERT INTO t1 SELECT * FROM t2} 309e4dd73b4Sdrh 310e4dd73b4Sdrh# Select 20000 rows from the table at random. 311e4dd73b4Sdrh# 31291c58e23Sdrhspeed_trial speed2-random1 50000 row { 313e4dd73b4Sdrh SELECT rowid FROM t1 ORDER BY random() LIMIT 20000 314e4dd73b4Sdrh} 315e4dd73b4Sdrh 316e4dd73b4Sdrh# Delete 20000 random rows from the table. 317e4dd73b4Sdrh# 31891c58e23Sdrhspeed_trial speed2-random-del1 20000 row { 319e4dd73b4Sdrh DELETE FROM t1 WHERE rowid IN 320e4dd73b4Sdrh (SELECT rowid FROM t1 ORDER BY random() LIMIT 20000) 321e4dd73b4Sdrh} 32291c58e23Sdrhdo_test speed2-1.1 { 323e4dd73b4Sdrh db one {SELECT count(*) FROM t1} 324e4dd73b4Sdrh} 30000 325e4dd73b4Sdrh 326e4dd73b4Sdrh 327e4dd73b4Sdrh# Delete 20000 more rows at random from the table. 328e4dd73b4Sdrh# 32991c58e23Sdrhspeed_trial speed2-random-del2 20000 row { 330e4dd73b4Sdrh DELETE FROM t1 WHERE rowid IN 331e4dd73b4Sdrh (SELECT rowid FROM t1 ORDER BY random() LIMIT 20000) 332e4dd73b4Sdrh} 33391c58e23Sdrhdo_test speed2-1.2 { 334e4dd73b4Sdrh db one {SELECT count(*) FROM t1} 335e4dd73b4Sdrh} 10000 336dd92431aSdrhspeed_trial_summary speed2 337dd92431aSdrh 338e4dd73b4Sdrh 339e4dd73b4Sdrhfinish_test 340