xref: /sqlite-3.40.0/test/speed4p.explain (revision 4c68e6d2)
1*4c68e6d2Sdrh# 2007 October 23
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. More specifically,
13*4c68e6d2Sdrh# the focus is on the speed of:
14*4c68e6d2Sdrh#
15*4c68e6d2Sdrh#   * joins
16*4c68e6d2Sdrh#   * views
17*4c68e6d2Sdrh#   * sub-selects
18*4c68e6d2Sdrh#   * triggers
19*4c68e6d2Sdrh#
20*4c68e6d2Sdrh# $Id: speed4p.explain,v 1.1 2008/04/16 12:57:48 drh Exp $
21*4c68e6d2Sdrh#
22*4c68e6d2Sdrh
23*4c68e6d2Sdrhset testdir [file dirname $argv0]
24*4c68e6d2Sdrhsource $testdir/tester.tcl
25*4c68e6d2Sdrhspeed_trial_init speed1
26*4c68e6d2Sdrh
27*4c68e6d2Sdrh# Set a uniform random seed
28*4c68e6d2Sdrhexpr srand(0)
29*4c68e6d2Sdrh
30*4c68e6d2Sdrhset sqlout [open speed1.txt w]
31*4c68e6d2Sdrhproc tracesql {sql} {
32*4c68e6d2Sdrh  puts $::sqlout $sql\;
33*4c68e6d2Sdrh}
34*4c68e6d2Sdrh#db trace tracesql
35*4c68e6d2Sdrh
36*4c68e6d2Sdrh# The number_name procedure below converts its argment (an integer)
37*4c68e6d2Sdrh# into a string which is the English-language name for that number.
38*4c68e6d2Sdrh#
39*4c68e6d2Sdrh# Example:
40*4c68e6d2Sdrh#
41*4c68e6d2Sdrh#     puts [number_name 123]   ->  "one hundred twenty three"
42*4c68e6d2Sdrh#
43*4c68e6d2Sdrhset ones {zero one two three four five six seven eight nine
44*4c68e6d2Sdrh          ten eleven twelve thirteen fourteen fifteen sixteen seventeen
45*4c68e6d2Sdrh          eighteen nineteen}
46*4c68e6d2Sdrhset tens {{} ten twenty thirty forty fifty sixty seventy eighty ninety}
47*4c68e6d2Sdrhproc number_name {n} {
48*4c68e6d2Sdrh  if {$n>=1000} {
49*4c68e6d2Sdrh    set txt "[number_name [expr {$n/1000}]] thousand"
50*4c68e6d2Sdrh    set n [expr {$n%1000}]
51*4c68e6d2Sdrh  } else {
52*4c68e6d2Sdrh    set txt {}
53*4c68e6d2Sdrh  }
54*4c68e6d2Sdrh  if {$n>=100} {
55*4c68e6d2Sdrh    append txt " [lindex $::ones [expr {$n/100}]] hundred"
56*4c68e6d2Sdrh    set n [expr {$n%100}]
57*4c68e6d2Sdrh  }
58*4c68e6d2Sdrh  if {$n>=20} {
59*4c68e6d2Sdrh    append txt " [lindex $::tens [expr {$n/10}]]"
60*4c68e6d2Sdrh    set n [expr {$n%10}]
61*4c68e6d2Sdrh  }
62*4c68e6d2Sdrh  if {$n>0} {
63*4c68e6d2Sdrh    append txt " [lindex $::ones $n]"
64*4c68e6d2Sdrh  }
65*4c68e6d2Sdrh  set txt [string trim $txt]
66*4c68e6d2Sdrh  if {$txt==""} {set txt zero}
67*4c68e6d2Sdrh  return $txt
68*4c68e6d2Sdrh}
69*4c68e6d2Sdrh
70*4c68e6d2Sdrh# Summary of tests:
71*4c68e6d2Sdrh#
72*4c68e6d2Sdrh#   speed4p-join1: Join three tables using IPK index.
73*4c68e6d2Sdrh#   speed4p-join2: Join three tables using an index.
74*4c68e6d2Sdrh#   speed4p-join3: Join two tables without an index.
75*4c68e6d2Sdrh#
76*4c68e6d2Sdrh#   speed4p-view1:  Querying a view.
77*4c68e6d2Sdrh#   speed4p-table1: Same queries as in speed4p-view1, but run directly against
78*4c68e6d2Sdrh#                  the tables for comparison purposes.
79*4c68e6d2Sdrh#
80*4c68e6d2Sdrh#   speed4p-subselect1: A SELECT statement that uses many sub-queries..
81*4c68e6d2Sdrh#
82*4c68e6d2Sdrh#   speed4p-trigger1: An INSERT statement that fires a trigger.
83*4c68e6d2Sdrh#   speed4p-trigger2: An UPDATE statement that fires a trigger.
84*4c68e6d2Sdrh#   speed4p-trigger3: A DELETE statement that fires a trigger.
85*4c68e6d2Sdrh#   speed4p-notrigger1: Same operation as trigger1, but without the trigger.
86*4c68e6d2Sdrh#   speed4p-notrigger2:        "          trigger2           "
87*4c68e6d2Sdrh#   speed4p-notrigger3:        "          trigger3           "
88*4c68e6d2Sdrh#
89*4c68e6d2Sdrh
90*4c68e6d2Sdrh# Set up the schema. Each of the tables t1, t2 and t3 contain 50,000 rows.
91*4c68e6d2Sdrh# This creates a database of around 16MB.
92*4c68e6d2Sdrhexecsql {
93*4c68e6d2Sdrh  PRAGMA page_size=1024;
94*4c68e6d2Sdrh  PRAGMA cache_size=8192;
95*4c68e6d2Sdrh  PRAGMA locking_mode=EXCLUSIVE;
96*4c68e6d2Sdrh  BEGIN;
97*4c68e6d2Sdrh  CREATE TABLE t1(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);
98*4c68e6d2Sdrh  CREATE TABLE t2(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);
99*4c68e6d2Sdrh  CREATE TABLE t3(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);
100*4c68e6d2Sdrh
101*4c68e6d2Sdrh  CREATE VIEW v1 AS SELECT rowid, i, t FROM t1;
102*4c68e6d2Sdrh  CREATE VIEW v2 AS SELECT rowid, i, t FROM t2;
103*4c68e6d2Sdrh  CREATE VIEW v3 AS SELECT rowid, i, t FROM t3;
104*4c68e6d2Sdrh}
105*4c68e6d2Sdrhfor {set jj 1} {$jj <= 3} {incr jj} {
106*4c68e6d2Sdrh  set stmt [string map "%T% t$jj" {INSERT INTO %T% VALUES(NULL, $i, $t)}]
107*4c68e6d2Sdrh  for {set ii 0} {$ii < 50000} {incr ii} {
108*4c68e6d2Sdrh    set i [expr {int(rand()*50000)}]
109*4c68e6d2Sdrh    set t [number_name $i]
110*4c68e6d2Sdrh    execsql $stmt
111*4c68e6d2Sdrh  }
112*4c68e6d2Sdrh}
113*4c68e6d2Sdrhexecsql {
114*4c68e6d2Sdrh  CREATE INDEX i1 ON t1(t);
115*4c68e6d2Sdrh  CREATE INDEX i2 ON t2(t);
116*4c68e6d2Sdrh  CREATE INDEX i3 ON t3(t);
117*4c68e6d2Sdrh  COMMIT;
118*4c68e6d2Sdrh}
119*4c68e6d2Sdrh
120*4c68e6d2Sdrh# Before running these tests, disable the compiled statement cache built into
121*4c68e6d2Sdrh# the Tcl interface. This is because we want to test the speed of SQL
122*4c68e6d2Sdrh# compilation as well as execution.
123*4c68e6d2Sdrh#
124*4c68e6d2Sdrhdb cache size 0
125*4c68e6d2Sdrh
126*4c68e6d2Sdrh# Join t1, t2, t3 on IPK.
127*4c68e6d2Sdrhset sql "SELECT * FROM t1, t2, t3 WHERE t1.oid = t2.oid AND t2.oid = t3.oid"
128*4c68e6d2Sdrhexplain $sql
129*4c68e6d2Sdrhspeed_trial speed4p-join1 50000 row $sql
130*4c68e6d2Sdrh
131*4c68e6d2Sdrh# Join t1, t2, t3 on the non-IPK index.
132*4c68e6d2Sdrhset sql "SELECT * FROM t1, t2, t3 WHERE t1.t = t2.t AND t2.t = t3.t"
133*4c68e6d2Sdrhexplain $sql
134*4c68e6d2Sdrhspeed_trial speed4p-join2 50000 row $sql
135*4c68e6d2Sdrh
136*4c68e6d2Sdrh# Run 10000 simple queries against the views.
137*4c68e6d2Sdrhset script {
138*4c68e6d2Sdrh  for {set ii 1} {$ii < 10000} {incr ii} {
139*4c68e6d2Sdrh    set v [expr {$ii*3}]
140*4c68e6d2Sdrh    set t [expr {$ii%3+1}]
141*4c68e6d2Sdrh    db eval "SELECT * FROM v$t WHERE rowid = \$v"
142*4c68e6d2Sdrh  }
143*4c68e6d2Sdrh}
144*4c68e6d2Sdrhexplain {SELECT * FROm v1 WHERE rowid=$v}
145*4c68e6d2Sdrhspeed_trial_tcl speed4p-view1 10000 stmt $script
146*4c68e6d2Sdrh
147*4c68e6d2Sdrh# Run the same 10000 simple queries as in the previous test case against
148*4c68e6d2Sdrh# the underlying tables. The compiled vdbe programs should be identical, so
149*4c68e6d2Sdrh# the only difference in running time is the extra time taken to compile
150*4c68e6d2Sdrh# the view definitions.
151*4c68e6d2Sdrh#
152*4c68e6d2Sdrhset script {
153*4c68e6d2Sdrh  for {set ii 1} {$ii < 10000} {incr ii} {
154*4c68e6d2Sdrh    set v [expr {$ii*3}]
155*4c68e6d2Sdrh    set t [expr {$ii%3+1}]
156*4c68e6d2Sdrh    db eval "SELECT t FROM t$t WHERE rowid = \$v"
157*4c68e6d2Sdrh  }
158*4c68e6d2Sdrh}
159*4c68e6d2Sdrhexplain {SELECT * FROM t1 WHERE rowid=$v}
160*4c68e6d2Sdrhspeed_trial_tcl speed4p-table1 10000 stmt $script
161*4c68e6d2Sdrh
162*4c68e6d2Sdrh# Run a SELECT that uses sub-queries 10000 times. A total of 30000 sub-selects.
163*4c68e6d2Sdrh#
164*4c68e6d2Sdrhset script {
165*4c68e6d2Sdrh  for {set ii 1} {$ii < 10000} {incr ii} {
166*4c68e6d2Sdrh    set v [expr {$ii*3}]
167*4c68e6d2Sdrh    db eval {
168*4c68e6d2Sdrh      SELECT (SELECT t FROM t1 WHERE rowid = $v),
169*4c68e6d2Sdrh             (SELECT t FROM t2 WHERE rowid = $v),
170*4c68e6d2Sdrh             (SELECT t FROM t3 WHERE rowid = $v)
171*4c68e6d2Sdrh    }
172*4c68e6d2Sdrh  }
173*4c68e6d2Sdrh}
174*4c68e6d2Sdrhexplain {
175*4c68e6d2Sdrh      SELECT (SELECT t FROM t1 WHERE rowid = $v),
176*4c68e6d2Sdrh             (SELECT t FROM t2 WHERE rowid = $v),
177*4c68e6d2Sdrh             (SELECT t FROM t3 WHERE rowid = $v)
178*4c68e6d2Sdrh}
179*4c68e6d2Sdrhspeed_trial_tcl speed4p-subselect1 10000 stmt $script
180*4c68e6d2Sdrh
181*4c68e6d2Sdrh# The following block tests the speed of some DML statements that cause
182*4c68e6d2Sdrh# triggers to fire.
183*4c68e6d2Sdrh#
184*4c68e6d2Sdrhexecsql {
185*4c68e6d2Sdrh  CREATE TABLE log(op TEXT, r INTEGER, i INTEGER, t TEXT);
186*4c68e6d2Sdrh  CREATE TABLE t4(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);
187*4c68e6d2Sdrh  CREATE TRIGGER t4_trigger1 AFTER INSERT ON t4 BEGIN
188*4c68e6d2Sdrh    INSERT INTO log VALUES('INSERT INTO t4', new.rowid, new.i, new.t);
189*4c68e6d2Sdrh  END;
190*4c68e6d2Sdrh  CREATE TRIGGER t4_trigger2 AFTER UPDATE ON t4 BEGIN
191*4c68e6d2Sdrh    INSERT INTO log VALUES('UPDATE OF t4', new.rowid, new.i, new.t);
192*4c68e6d2Sdrh  END;
193*4c68e6d2Sdrh  CREATE TRIGGER t4_trigger3 AFTER DELETE ON t4 BEGIN
194*4c68e6d2Sdrh    INSERT INTO log VALUES('DELETE OF t4', old.rowid, old.i, old.t);
195*4c68e6d2Sdrh  END;
196*4c68e6d2Sdrh  BEGIN;
197*4c68e6d2Sdrh}
198*4c68e6d2Sdrhset list {}
199*4c68e6d2Sdrhfor {set ii 1} {$ii < 10000} {incr ii} {
200*4c68e6d2Sdrh  lappend list $ii [number_name $ii]
201*4c68e6d2Sdrh}
202*4c68e6d2Sdrhset script {
203*4c68e6d2Sdrh  foreach {ii name} $::list {
204*4c68e6d2Sdrh    db eval {INSERT INTO t4 VALUES(NULL, $ii, $name)}
205*4c68e6d2Sdrh  }
206*4c68e6d2Sdrh}
207*4c68e6d2Sdrhexplain {INSERT INTO t4 VALUES(NULL, $ii, $name)}
208*4c68e6d2Sdrhspeed_trial_tcl speed4p-trigger1 10000 stmt $script
209*4c68e6d2Sdrh
210*4c68e6d2Sdrhset list {}
211*4c68e6d2Sdrhfor {set ii 1} {$ii < 20000} {incr ii 2} {
212*4c68e6d2Sdrh  set ii2 [expr {$ii*2}]
213*4c68e6d2Sdrh  lappend list $ii $ii2 [number_name $ii2]
214*4c68e6d2Sdrh}
215*4c68e6d2Sdrhset script {
216*4c68e6d2Sdrh  foreach {ii ii2 name} $::list {
217*4c68e6d2Sdrh    db eval {
218*4c68e6d2Sdrh      UPDATE t4 SET i = $ii2, t = $name WHERE rowid = $ii;
219*4c68e6d2Sdrh    }
220*4c68e6d2Sdrh  }
221*4c68e6d2Sdrh}
222*4c68e6d2Sdrhexplain {UPDATE t4 SET i = $ii2, t = $name WHERE rowid = $ii}
223*4c68e6d2Sdrhspeed_trial_tcl speed4p-trigger2 10000 stmt $script
224*4c68e6d2Sdrh
225*4c68e6d2Sdrhset script {
226*4c68e6d2Sdrh  for {set ii 1} {$ii < 20000} {incr ii 2} {
227*4c68e6d2Sdrh    db eval {DELETE FROM t4 WHERE rowid = $ii}
228*4c68e6d2Sdrh  }
229*4c68e6d2Sdrh}
230*4c68e6d2Sdrhexplain {DELETE FROM t4 WHERE rowid = $ii}
231*4c68e6d2Sdrhspeed_trial_tcl speed4p-trigger3 10000 stmt $script
232*4c68e6d2Sdrhexecsql {COMMIT}
233*4c68e6d2Sdrh
234*4c68e6d2Sdrh# The following block contains the same tests as the above block that
235*4c68e6d2Sdrh# tests triggers, with one crucial difference: no triggers are defined.
236*4c68e6d2Sdrh# So the difference in speed between these tests and the preceding ones
237*4c68e6d2Sdrh# is the amount of time taken to compile and execute the trigger programs.
238*4c68e6d2Sdrh#
239*4c68e6d2Sdrhexecsql {
240*4c68e6d2Sdrh  DROP TABLE t4;
241*4c68e6d2Sdrh  DROP TABLE log;
242*4c68e6d2Sdrh  VACUUM;
243*4c68e6d2Sdrh  CREATE TABLE t4(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);
244*4c68e6d2Sdrh  BEGIN;
245*4c68e6d2Sdrh}
246*4c68e6d2Sdrhset list {}
247*4c68e6d2Sdrhfor {set ii 1} {$ii < 10000} {incr ii} {
248*4c68e6d2Sdrh  lappend list $ii [number_name $ii]
249*4c68e6d2Sdrh}
250*4c68e6d2Sdrhset script {
251*4c68e6d2Sdrh  foreach {ii name} $::list {
252*4c68e6d2Sdrh    db eval {INSERT INTO t4 VALUES(NULL, $ii, $name);}
253*4c68e6d2Sdrh  }
254*4c68e6d2Sdrh}
255*4c68e6d2Sdrhexplain {INSERT INTO t4 VALUES(NULL, $ii, $name)}
256*4c68e6d2Sdrhspeed_trial_tcl speed4p-notrigger1 10000 stmt $script
257*4c68e6d2Sdrh
258*4c68e6d2Sdrhset list {}
259*4c68e6d2Sdrhfor {set ii 1} {$ii < 20000} {incr ii 2} {
260*4c68e6d2Sdrh  set ii2 [expr {$ii*2}]
261*4c68e6d2Sdrh  lappend list $ii $ii2 [number_name $ii2]
262*4c68e6d2Sdrh}
263*4c68e6d2Sdrhset script {
264*4c68e6d2Sdrh  foreach {ii ii2 name} $::list {
265*4c68e6d2Sdrh    db eval {
266*4c68e6d2Sdrh      UPDATE t4 SET i = $ii2, t = $name WHERE rowid = $ii;
267*4c68e6d2Sdrh    }
268*4c68e6d2Sdrh  }
269*4c68e6d2Sdrh}
270*4c68e6d2Sdrhexplain {UPDATE t4 SET i = $ii2, t = $name WHERE rowid = $ii}
271*4c68e6d2Sdrhspeed_trial_tcl speed4p-notrigger2 10000 stmt $script
272*4c68e6d2Sdrh
273*4c68e6d2Sdrhset script {
274*4c68e6d2Sdrh  for {set ii 1} {$ii < 20000} {incr ii 2} {
275*4c68e6d2Sdrh    db eval {DELETE FROM t4 WHERE rowid = $ii}
276*4c68e6d2Sdrh  }
277*4c68e6d2Sdrh}
278*4c68e6d2Sdrhexplain {DELETE FROM t4 WHERE rowid = $ii}
279*4c68e6d2Sdrhspeed_trial_tcl speed4p-notrigger3 10000 stmt $script
280*4c68e6d2Sdrhexecsql {COMMIT}
281*4c68e6d2Sdrh
282*4c68e6d2Sdrhspeed_trial_summary speed4
283*4c68e6d2Sdrhfinish_test
284