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