blob: e32feddf304e2940ae4cedbf53fb9d2cf9b4106d [file] [log] [blame]
drh4c68e6d2008-04-16 12:57:48 +00001# 2008 March 21
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# This is a copy of speed1.test modified to user prepared statements.
15#
16# $Id: speed1p.explain,v 1.1 2008/04/16 12:57:48 drh Exp $
17#
18
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 speed1p-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 list {}
87for {set i 1} {$i<=50000} {incr i} {
88 set r [expr {int(rand()*500000)}]
89 set x [number_name $r]
90 lappend list $i $r $x
91}
92set script {
93 foreach {i r x} $::list {
94 db eval {INSERT INTO t1 VALUES($i,$r,$x)}
95 }
96}
97explain {INSERT INTO t1 VALUES($i,$r,$x)}
98db eval BEGIN
99speed_trial_tcl speed1p-insert1 50000 row $script
100db eval COMMIT
101
102# 50000 INSERTs on an indexed table
103#
104set list {}
105for {set i 1} {$i<=50000} {incr i} {
106 set r [expr {int(rand()*500000)}]
107 set x [number_name $r]
108 lappend list $i $r $x
109}
110set script {
111 foreach {i r x} $::list {
112 db eval {INSERT INTO t2 VALUES($i,$r,$x)}
113 }
114}
115explain {INSERT INTO t2 VALUES($i,$r,$x)}
116db eval BEGIN
117speed_trial_tcl speed1p-insert2 50000 row $script
118db eval COMMIT
119
120
121
122# 50 SELECTs on an integer comparison. There is no index so
123# a full table scan is required.
124#
125set list {}
126for {set i 0} {$i<50} {incr i} {
127 set lwr [expr {$i*100}]
128 set upr [expr {($i+10)*100}]
129 lappend list $lwr $upr
130}
131set script {
132 foreach {lwr upr} $::list {
133 db eval {SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr}
134 }
135}
136explain {SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr}
137db eval BEGIN
138speed_trial_tcl speed1p-select1 [expr {50*50000}] row $script
139db eval COMMIT
140
141# 50 SELECTs on an LIKE comparison. There is no index so a full
142# table scan is required.
143#
144set list {}
145for {set i 0} {$i<50} {incr i} {
146 lappend list "%[number_name $i]%"
147}
148set script {
149 foreach pattern $::list {
150 db eval {SELECT count(*), avg(b) FROM t1 WHERE c LIKE $pattern}
151 }
152}
153explain {SELECT count(*), avg(b) FROM t1 WHERE c LIKE $pattern}
154db eval BEGIN
155speed_trial_tcl speed1p-select2 [expr {50*50000}] row $script
156db eval COMMIT
157
158# Create indices
159#
160explain {CREATE INDEX i1a ON t1(a)}
161explain {CREATE INDEX i1b ON t1(b)}
162db eval BEGIN
163speed_trial speed1p-createidx 150000 row {
164 CREATE INDEX i1a ON t1(a);
165 CREATE INDEX i1b ON t1(b);
166 CREATE INDEX i1c ON t1(c);
167}
168db eval COMMIT
169
170# 5000 SELECTs on an integer comparison where the integer is
171# indexed.
172#
173set list {}
174for {set i 0} {$i<5000} {incr i} {
175 set lwr [expr {$i*100}]
176 set upr [expr {($i+10)*100}]
177 lappend list $lwr $upr
178}
179set script {
180 foreach {lwr upr} $::list {
181 db eval {SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr}
182 }
183}
184explain {SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr}
185db eval BEGIN
186speed_trial_tcl speed1p-select3 5000 stmt $script
187db eval COMMIT
188
189# 100000 random SELECTs against rowid.
190#
191set list {}
192for {set i 1} {$i<=100000} {incr i} {
193 set id [expr {int(rand()*50000)+1}]
194 lappend list $id
195}
196set script {
197 foreach id $::list {
198 db eval {SELECT c FROM t1 WHERE rowid=$id}
199 }
200}
201explain {SELECT c FROM t1 WHERE rowid=$id}
202db eval BEGIN
203speed_trial_tcl speed1p-select4 100000 row $script
204db eval COMMIT
205
206# 100000 random SELECTs against a unique indexed column.
207#
208set list {}
209for {set i 1} {$i<=100000} {incr i} {
210 set id [expr {int(rand()*50000)+1}]
211 lappend list $id
212}
213set script {
214 foreach id $::list {
215 db eval {SELECT c FROM t1 WHERE a=$id}
216 }
217}
218explain {SELECT c FROM t1 WHERE a=$id}
219db eval BEGIN
220speed_trial_tcl speed1p-select5 100000 row $script
221db eval COMMIT
222
223# 50000 random SELECTs against an indexed column text column
224#
225set list [db eval {SELECT c FROM t1 ORDER BY random() LIMIT 50000}]
226set script {
227 foreach c $::list {
228 db eval {SELECT c FROM t1 WHERE c=$c}
229 }
230}
231explain {SELECT c FROM t1 WHERE c=$c}
232db eval BEGIN
233speed_trial_tcl speed1p-select6 50000 row $script
234db eval COMMIT
235
236
237# Vacuum
238speed_trial speed1p-vacuum 100000 row VACUUM
239
240# 5000 updates of ranges where the field being compared is indexed.
241#
242set list {}
243for {set i 0} {$i<5000} {incr i} {
244 set lwr [expr {$i*2}]
245 set upr [expr {($i+1)*2}]
246 lappend list $lwr $upr
247}
248set script {
249 foreach {lwr upr} $::list {
250 db eval {UPDATE t1 SET b=b*2 WHERE a>=$lwr AND a<$upr}
251 }
252}
253explain {UPDATE t1 SET b=b*2 WHERE a>=$lwr AND a<$upr}
254db eval BEGIN
255speed_trial_tcl speed1p-update1 5000 stmt $script
256db eval COMMIT
257
258# 50000 single-row updates. An index is used to find the row quickly.
259#
260set list {}
261for {set i 0} {$i<50000} {incr i} {
262 set r [expr {int(rand()*500000)}]
263 lappend list $i $r
264}
265set script {
266 foreach {i r} $::list {
267 db eval {UPDATE t1 SET b=$r WHERE a=$i}
268 }
269}
270explain {UPDATE t1 SET b=$r WHERE a=$i}
271db eval BEGIN
272speed_trial_tcl speed1p-update2 50000 row $script
273db eval COMMIT
274
275# 1 big text update that touches every row in the table.
276#
277explain {UPDATE t1 SET c=a}
278speed_trial speed1p-update3 50000 row {
279 UPDATE t1 SET c=a;
280}
281
282# Many individual text updates. Each row in the table is
283# touched through an index.
284#
285set list {}
286for {set i 1} {$i<=50000} {incr i} {
287 set r [expr {int(rand()*500000)}]
288 lappend list $i [number_name $r]
289}
290set script {
291 foreach {i x} $::list {
292 db eval {UPDATE t1 SET c=$x WHERE a=$i}
293 }
294}
295explain {UPDATE t1 SET c=$x WHERE a=$i}
296db eval BEGIN
297speed_trial_tcl speed1p-update4 50000 row $script
298db eval COMMIT
299
300# Delete all content in a table.
301#
302explain {DELETE FROM t1}
303speed_trial speed1p-delete1 50000 row {DELETE FROM t1}
304
305# Copy one table into another
306#
307explain {INSERT INTO t1 SELECT * FROM t2}
308speed_trial speed1p-copy1 50000 row {INSERT INTO t1 SELECT * FROM t2}
309
310# Delete all content in a table, one row at a time.
311#
312explain {DELETE FROM t1 WHERE 1}
313speed_trial speed1p-delete2 50000 row {DELETE FROM t1 WHERE 1}
314
315# Refill the table yet again
316#
317speed_trial speed1p-copy2 50000 row {INSERT INTO t1 SELECT * FROM t2}
318
319# Drop the table and recreate it without its indices.
320#
321explain {DROP TABLE t1}
322explain {CREATE TABLE tX(a INTEGER, b INTEGER, c TEXT)}
323db eval BEGIN
324speed_trial speed1p-drop1 50000 row {
325 DROP TABLE t1;
326 CREATE TABLE t1(a INTEGER, b INTEGER, c TEXT);
327}
328db eval COMMIT
329
330# Refill the table yet again. This copy should be faster because
331# there are no indices to deal with.
332#
333speed_trial speed1p-copy3 50000 row {INSERT INTO t1 SELECT * FROM t2}
334
335# Select 20000 rows from the table at random.
336#
337explain {SELECT rowid FROM t1 ORDER BY random() LIMIT 20000}
338speed_trial speed1p-random1 50000 row {
339 SELECT rowid FROM t1 ORDER BY random() LIMIT 20000
340}
341
342# Delete 20000 random rows from the table.
343#
344explain {DELETE FROM t1 WHERE rowid IN
345 (SELECT rowid FROM t1 ORDER BY random() LIMIT 20000)}
346speed_trial speed1p-random-del1 20000 row {
347 DELETE FROM t1 WHERE rowid IN
348 (SELECT rowid FROM t1 ORDER BY random() LIMIT 20000)
349}
350do_test speed1p-1.1 {
351 db one {SELECT count(*) FROM t1}
352} 30000
353
354
355# Delete 20000 more rows at random from the table.
356#
357speed_trial speed1p-random-del2 20000 row {
358 DELETE FROM t1 WHERE rowid IN
359 (SELECT rowid FROM t1 ORDER BY random() LIMIT 20000)
360}
361do_test speed1p-1.2 {
362 db one {SELECT count(*) FROM t1}
363} 10000
364speed_trial_summary speed1
365
366finish_test