xref: /sqlite-3.40.0/test/cost.test (revision 8210233c)
12dd3cdcfSdan# 2014-04-26
22dd3cdcfSdan#
32dd3cdcfSdan# The author disclaims copyright to this source code.  In place of
42dd3cdcfSdan# a legal notice, here is a blessing:
52dd3cdcfSdan#
62dd3cdcfSdan#    May you do good and not evil.
72dd3cdcfSdan#    May you find forgiveness for yourself and forgive others.
82dd3cdcfSdan#    May you share freely, never taking more than you give.
92dd3cdcfSdan#
102dd3cdcfSdan#***********************************************************************
112dd3cdcfSdan#
122dd3cdcfSdan
132dd3cdcfSdanset testdir [file dirname $argv0]
142dd3cdcfSdansource $testdir/tester.tcl
152dd3cdcfSdanset testprefix cost
162dd3cdcfSdan
172dd3cdcfSdan
182dd3cdcfSdando_execsql_test 1.1 {
192dd3cdcfSdan  CREATE TABLE t3(id INTEGER PRIMARY KEY, b NOT NULL);
202dd3cdcfSdan  CREATE TABLE t4(c, d, e);
212dd3cdcfSdan  CREATE UNIQUE INDEX i3 ON t3(b);
222dd3cdcfSdan  CREATE UNIQUE INDEX i4 ON t4(c, d);
232dd3cdcfSdan}
242dd3cdcfSdando_eqp_test 1.2 {
252dd3cdcfSdan  SELECT e FROM t3, t4 WHERE b=c ORDER BY b, d;
262dd3cdcfSdan} {
27b3f0276bSdrh  QUERY PLAN
28*8210233cSdrh  |--SCAN t3 USING COVERING INDEX i3
29*8210233cSdrh  `--SEARCH t4 USING INDEX i4 (c=?)
302dd3cdcfSdan}
312dd3cdcfSdan
322dd3cdcfSdan
332dd3cdcfSdando_execsql_test 2.1 {
342dd3cdcfSdan  CREATE TABLE t1(a, b);
352dd3cdcfSdan  CREATE INDEX i1 ON t1(a);
362dd3cdcfSdan}
372dd3cdcfSdan
382dd3cdcfSdan# It is better to use an index for ORDER BY than sort externally, even
392dd3cdcfSdan# if the index is a non-covering index.
402dd3cdcfSdando_eqp_test 2.2 {
412dd3cdcfSdan  SELECT * FROM t1 ORDER BY a;
42*8210233cSdrh} {SCAN t1 USING INDEX i1}
432dd3cdcfSdan
442dd3cdcfSdando_execsql_test 3.1 {
452dd3cdcfSdan  CREATE TABLE t5(a INTEGER PRIMARY KEY,b,c,d,e,f,g);
462dd3cdcfSdan  CREATE INDEX t5b ON t5(b);
472dd3cdcfSdan  CREATE INDEX t5c ON t5(c);
482dd3cdcfSdan  CREATE INDEX t5d ON t5(d);
492dd3cdcfSdan  CREATE INDEX t5e ON t5(e);
502dd3cdcfSdan  CREATE INDEX t5f ON t5(f);
512dd3cdcfSdan  CREATE INDEX t5g ON t5(g);
522dd3cdcfSdan}
532dd3cdcfSdan
542dd3cdcfSdando_eqp_test 3.2 {
552dd3cdcfSdan  SELECT a FROM t5
562dd3cdcfSdan  WHERE b IS NULL OR c IS NULL OR d IS NULL
572dd3cdcfSdan  ORDER BY a;
582dd3cdcfSdan} {
59b3f0276bSdrh  QUERY PLAN
605d72d924Sdrh  |--MULTI-INDEX OR
61bd462bccSdrh  |  |--INDEX 1
62*8210233cSdrh  |  |  `--SEARCH t5 USING INDEX t5b (b=?)
63bd462bccSdrh  |  |--INDEX 2
64*8210233cSdrh  |  |  `--SEARCH t5 USING INDEX t5c (c=?)
65bd462bccSdrh  |  `--INDEX 3
66*8210233cSdrh  |     `--SEARCH t5 USING INDEX t5d (d=?)
67b3f0276bSdrh  `--USE TEMP B-TREE FOR ORDER BY
682dd3cdcfSdan}
692dd3cdcfSdan
70440e6ff3Sdan#-------------------------------------------------------------------------
71440e6ff3Sdan# If there is no likelihood() or stat3 data, SQLite assumes that a closed
72440e6ff3Sdan# range scan (e.g. one constrained by "col BETWEEN ? AND ?" constraint)
7309e1df6cSdan# visits 1/64 of the rows in a table.
74440e6ff3Sdan#
7509e1df6cSdan# Note: 1/63 =~ 0.016
7609e1df6cSdan# Note: 1/65 =~ 0.015
77440e6ff3Sdan#
78440e6ff3Sdanreset_db
79440e6ff3Sdando_execsql_test 4.1 {
80440e6ff3Sdan  CREATE TABLE t1(a, b);
81440e6ff3Sdan  CREATE INDEX i1 ON t1(a);
82440e6ff3Sdan  CREATE INDEX i2 ON t1(b);
83440e6ff3Sdan}
84440e6ff3Sdando_eqp_test 4.2 {
8509e1df6cSdan  SELECT * FROM t1 WHERE likelihood(a=?, 0.014) AND b BETWEEN ? AND ?;
86*8210233cSdrh} {SEARCH t1 USING INDEX i1 (a=?)}
87b3f0276bSdrh
88440e6ff3Sdando_eqp_test 4.3 {
8909e1df6cSdan  SELECT * FROM t1 WHERE likelihood(a=?, 0.016) AND b BETWEEN ? AND ?;
90*8210233cSdrh} {SEARCH t1 USING INDEX i2 (b>? AND b<?)}
912dd3cdcfSdan
922dd3cdcfSdan
937de2a1faSdan#-------------------------------------------------------------------------
947de2a1faSdan#
957de2a1faSdanreset_db
967de2a1faSdando_execsql_test 5.1 {
977de2a1faSdan  CREATE TABLE t2(x, y);
987de2a1faSdan  CREATE INDEX t2i1 ON t2(x);
997de2a1faSdan}
1007de2a1faSdan
1017de2a1faSdando_eqp_test 5.2 {
1027de2a1faSdan  SELECT * FROM t2 ORDER BY x, y;
10375525cbeSdan} {
104b3f0276bSdrh  QUERY PLAN
105*8210233cSdrh  |--SCAN t2 USING INDEX t2i1
106b3f0276bSdrh  `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
10775525cbeSdan}
1087de2a1faSdan
1097de2a1faSdando_eqp_test 5.3 {
1107de2a1faSdan  SELECT * FROM t2 WHERE x BETWEEN ? AND ? ORDER BY rowid;
11109e1df6cSdan} {
112b3f0276bSdrh  QUERY PLAN
113*8210233cSdrh  |--SEARCH t2 USING INDEX t2i1 (x>? AND x<?)
114b3f0276bSdrh  `--USE TEMP B-TREE FOR ORDER BY
11509e1df6cSdan}
1167de2a1faSdan
1177de2a1faSdan# where7.test, where8.test:
1187de2a1faSdan#
1197de2a1faSdando_execsql_test 6.1 {
1207de2a1faSdan  CREATE TABLE t3(a INTEGER PRIMARY KEY, b, c);
1217de2a1faSdan  CREATE INDEX t3i1 ON t3(b);
1227de2a1faSdan  CREATE INDEX t3i2 ON t3(c);
1237de2a1faSdan}
1247de2a1faSdan
1257de2a1faSdando_eqp_test 6.2 {
1267de2a1faSdan  SELECT a FROM t3 WHERE (b BETWEEN 2 AND 4) OR c=100 ORDER BY a
1277de2a1faSdan} {
128b3f0276bSdrh  QUERY PLAN
1295d72d924Sdrh  |--MULTI-INDEX OR
130bd462bccSdrh  |  |--INDEX 1
131*8210233cSdrh  |  |  `--SEARCH t3 USING INDEX t3i1 (b>? AND b<?)
132bd462bccSdrh  |  `--INDEX 2
133*8210233cSdrh  |     `--SEARCH t3 USING INDEX t3i2 (c=?)
134b3f0276bSdrh  `--USE TEMP B-TREE FOR ORDER BY
1357de2a1faSdan}
1367de2a1faSdan
1377de2a1faSdan#-------------------------------------------------------------------------
1387de2a1faSdan#
1397de2a1faSdanreset_db
1407de2a1faSdando_execsql_test 7.1 {
1417de2a1faSdan  CREATE TABLE t1(a INTEGER PRIMARY KEY,b,c,d,e,f,g);
1427de2a1faSdan  CREATE INDEX t1b ON t1(b);
1437de2a1faSdan  CREATE INDEX t1c ON t1(c);
1447de2a1faSdan  CREATE INDEX t1d ON t1(d);
1457de2a1faSdan  CREATE INDEX t1e ON t1(e);
1467de2a1faSdan  CREATE INDEX t1f ON t1(f);
1477de2a1faSdan  CREATE INDEX t1g ON t1(g);
1487de2a1faSdan}
1497de2a1faSdan
1507de2a1faSdando_eqp_test 7.2 {
1517de2a1faSdan  SELECT a FROM t1
1527de2a1faSdan     WHERE (b>=950 AND b<=1010) OR (b IS NULL AND c NOT NULL)
1537de2a1faSdan  ORDER BY a
1547de2a1faSdan} {
155b3f0276bSdrh  QUERY PLAN
1565d72d924Sdrh  |--MULTI-INDEX OR
157bd462bccSdrh  |  |--INDEX 1
158*8210233cSdrh  |  |  `--SEARCH t1 USING INDEX t1b (b>? AND b<?)
159bd462bccSdrh  |  `--INDEX 2
160*8210233cSdrh  |     `--SEARCH t1 USING INDEX t1b (b=?)
161b3f0276bSdrh  `--USE TEMP B-TREE FOR ORDER BY
1627de2a1faSdan}
1637de2a1faSdan
1647de2a1faSdando_eqp_test 7.3 {
1657de2a1faSdan  SELECT rowid FROM t1
1667de2a1faSdan  WHERE (+b IS NULL AND c NOT NULL AND d NOT NULL)
1677de2a1faSdan        OR (b NOT NULL AND c IS NULL AND d NOT NULL)
1687de2a1faSdan        OR (b NOT NULL AND c NOT NULL AND d IS NULL)
169*8210233cSdrh} {SCAN t1}
1707de2a1faSdan
1715da73e1aSdando_eqp_test 7.4 {
1725da73e1aSdan  SELECT rowid FROM t1 WHERE (+b IS NULL AND c NOT NULL) OR c IS NULL
173*8210233cSdrh} {SCAN t1}
1745da73e1aSdan
1757de2a1faSdan#-------------------------------------------------------------------------
1767de2a1faSdan#
1777de2a1faSdanreset_db
1787de2a1faSdando_execsql_test 8.1 {
1797de2a1faSdan  CREATE TABLE composer(
1807de2a1faSdan    cid INTEGER PRIMARY KEY,
1817de2a1faSdan    cname TEXT
1827de2a1faSdan  );
1837de2a1faSdan  CREATE TABLE album(
1847de2a1faSdan    aid INTEGER PRIMARY KEY,
1857de2a1faSdan    aname TEXT
1867de2a1faSdan  );
1877de2a1faSdan  CREATE TABLE track(
1887de2a1faSdan    tid INTEGER PRIMARY KEY,
1897de2a1faSdan    cid INTEGER REFERENCES composer,
1907de2a1faSdan    aid INTEGER REFERENCES album,
1917de2a1faSdan    title TEXT
1927de2a1faSdan  );
1937de2a1faSdan  CREATE INDEX track_i1 ON track(cid);
1947de2a1faSdan  CREATE INDEX track_i2 ON track(aid);
1957de2a1faSdan}
1967de2a1faSdan
1977de2a1faSdando_eqp_test 8.2 {
1987de2a1faSdan  SELECT DISTINCT aname
1997de2a1faSdan    FROM album, composer, track
2007de2a1faSdan   WHERE cname LIKE '%bach%'
2017de2a1faSdan     AND unlikely(composer.cid=track.cid)
2027de2a1faSdan     AND unlikely(album.aid=track.aid);
2037de2a1faSdan} {
204b3f0276bSdrh  QUERY PLAN
205*8210233cSdrh  |--SCAN track
206*8210233cSdrh  |--SEARCH album USING INTEGER PRIMARY KEY (rowid=?)
207*8210233cSdrh  |--SEARCH composer USING INTEGER PRIMARY KEY (rowid=?)
208b3f0276bSdrh  `--USE TEMP B-TREE FOR DISTINCT
2097de2a1faSdan}
2107de2a1faSdan
211264d2b97Sdan#-------------------------------------------------------------------------
212264d2b97Sdan#
213264d2b97Sdando_execsql_test 9.1 {
214264d2b97Sdan  CREATE TABLE t1(
215264d2b97Sdan    a,b,c,d,e, f,g,h,i,j,
216264d2b97Sdan    k,l,m,n,o, p,q,r,s,t
217264d2b97Sdan  );
218264d2b97Sdan  CREATE INDEX i1 ON t1(k,l,m,n,o,p,q,r,s,t);
219264d2b97Sdan}
220264d2b97Sdando_test 9.2 {
221264d2b97Sdan  for {set i 0} {$i < 100} {incr i} {
222264d2b97Sdan    execsql { INSERT INTO t1 DEFAULT VALUES }
223264d2b97Sdan  }
224264d2b97Sdan  execsql {
225264d2b97Sdan    ANALYZE;
226264d2b97Sdan    CREATE INDEX i2 ON t1(a,b,c,d,e,f,g,h,i,j);
227264d2b97Sdan  }
228264d2b97Sdan} {}
229264d2b97Sdan
230264d2b97Sdanset L [list a=? b=? c=? d=? e=? f=? g=? h=? i=? j=?]
231264d2b97Sdanforeach {tn nTerm nRow} {
232264d2b97Sdan  1   1 10
23356c65c92Sdrh  2   2 10
234264d2b97Sdan  3   3  8
235264d2b97Sdan  4   4  7
23656c65c92Sdrh  5   5  7
237264d2b97Sdan  6   6  5
238264d2b97Sdan  7   7  5
239264d2b97Sdan  8   8  5
240264d2b97Sdan  9   9  5
241264d2b97Sdan  10 10  5
242264d2b97Sdan} {
243264d2b97Sdan  set w [join [lrange $L 0 [expr $nTerm-1]] " AND "]
244264d2b97Sdan  set p1 [expr ($nRow-1) / 100.0]
245264d2b97Sdan  set p2 [expr ($nRow+1) / 100.0]
246264d2b97Sdan
247264d2b97Sdan  set sql1 "SELECT * FROM t1 WHERE likelihood(k=?, $p1) AND $w"
248264d2b97Sdan  set sql2 "SELECT * FROM t1 WHERE likelihood(k=?, $p2) AND $w"
249264d2b97Sdan
250264d2b97Sdan  do_eqp_test 9.3.$tn.1 $sql1 {/INDEX i1/}
251264d2b97Sdan  do_eqp_test 9.3.$tn.2 $sql2 {/INDEX i2/}
252264d2b97Sdan}
253264d2b97Sdan
254264d2b97Sdan
2555a0b8b12Sdan#-------------------------------------------------------------------------
2565a0b8b12Sdan#
2575a0b8b12Sdan
2585a0b8b12Sdanifcapable stat4 {
2595a0b8b12Sdan  do_execsql_test 10.1 {
2605a0b8b12Sdan    CREATE TABLE t6(a, b, c);
2615a0b8b12Sdan    CREATE INDEX t6i1 ON t6(a, b);
2625a0b8b12Sdan    CREATE INDEX t6i2 ON t6(c);
2635a0b8b12Sdan  }
2645a0b8b12Sdan
2655a0b8b12Sdan  do_test 10.2 {
2665a0b8b12Sdan    for {set i 0} {$i < 16} {incr i} {
2675a0b8b12Sdan      execsql { INSERT INTO t6 VALUES($i%4, 'xyz', $i%8) }
2685a0b8b12Sdan    }
2695a0b8b12Sdan    execsql ANALYZE
2705a0b8b12Sdan  } {}
2715a0b8b12Sdan
2725a0b8b12Sdan  do_eqp_test 10.3 {
2735a0b8b12Sdan    SELECT rowid FROM t6 WHERE a=0 AND c=0
274*8210233cSdrh  } {SEARCH t6 USING INDEX t6i2 (c=?)}
2755a0b8b12Sdan
2765a0b8b12Sdan  do_eqp_test 10.4 {
2775a0b8b12Sdan    SELECT rowid FROM t6 WHERE a=0 AND b='xyz' AND c=0
278*8210233cSdrh  } {SEARCH t6 USING INDEX t6i2 (c=?)}
2795a0b8b12Sdan
2805a0b8b12Sdan  do_eqp_test 10.5 {
2815a0b8b12Sdan    SELECT rowid FROM t6 WHERE likelihood(a=0, 0.1) AND c=0
282*8210233cSdrh  } {SEARCH t6 USING INDEX t6i1 (a=?)}
2835a0b8b12Sdan
2845a0b8b12Sdan  do_eqp_test 10.6 {
2855a0b8b12Sdan    SELECT rowid FROM t6 WHERE likelihood(a=0, 0.1) AND b='xyz' AND c=0
286*8210233cSdrh  } {SEARCH t6 USING INDEX t6i1 (a=? AND b=?)}
2875a0b8b12Sdan}
288264d2b97Sdan
2892dd3cdcfSdanfinish_test
290