/ Check-in [53fff7d1]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Improvements to the XFER Optimization of the INSERT statement. (CVS 3736)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 53fff7d1f2f829010a2641c7738538b3155da4b2
User & Date: drh 2007-03-28 18:04:10
Context
2007-03-29
00:08
Patch so the the code compiles with -DSQLITE_OMIT_CHECK=1. (CVS 3737) check-in: 72cea358 user: drh tags: trunk
2007-03-28
18:04
Improvements to the XFER Optimization of the INSERT statement. (CVS 3736) check-in: 53fff7d1 user: drh tags: trunk
14:30
Correctly handle NULLs in IN operators. Ticket #2273. The changes in where.c and in the WhereLevel.aInLoop structure are not strictly necessary to fix this problem - they just make the code easier to read. Only the change in OP_Next/OP_Prev operator of vdbe.c is required. (CVS 3735) check-in: 26348556 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Show Whitespace Changes Patch

Changes to src/insert.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
1494
1495
1496
1497
1498
1499
1500

1501
1502
1503
1504
1505
1506
1507
1508
1509
1510



1511
1512
1513
1514
1515
1516
1517
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.177 2007/03/27 12:04:05 drh Exp $
*/
#include "sqliteInt.h"

/*
** Set P3 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
................................................................................
    emptyDestTest = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
    sqlite3VdbeJumpHere(v, addr1);
  }else{
    emptyDestTest = 0;
  }
  sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
  emptySrcTest = sqlite3VdbeAddOp(v, OP_Rewind, iSrc, 0);

  memRowid = pParse->nMem++;
  sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0);
  sqlite3VdbeAddOp(v, OP_MemStore, memRowid, 1);
  addr1 = sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0);
  sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
  addr2 = sqlite3VdbeAddOp(v, OP_NotExists, iDest, 0);
  sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, 
                    "PRIMARY KEY must be unique", P3_STATIC);
  sqlite3VdbeJumpHere(v, addr2);
  autoIncStep(pParse, counterMem);



  sqlite3VdbeAddOp(v, OP_RowData, iSrc, 0);
  sqlite3VdbeOp3(v, OP_Insert, iDest, OPFLAG_NCHANGE|OPFLAG_LASTROWID,
                    pDest->zName, 0);
  sqlite3VdbeAddOp(v, OP_Next, iSrc, addr1);
  autoIncEnd(pParse, iDbDest, pDest, counterMem);
  for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
    for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){







|







 







>










>
>
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.178 2007/03/28 18:04:10 drh Exp $
*/
#include "sqliteInt.h"

/*
** Set P3 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
................................................................................
    emptyDestTest = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
    sqlite3VdbeJumpHere(v, addr1);
  }else{
    emptyDestTest = 0;
  }
  sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
  emptySrcTest = sqlite3VdbeAddOp(v, OP_Rewind, iSrc, 0);
  if( pDest->iPKey>=0 ){
    memRowid = pParse->nMem++;
    sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0);
    sqlite3VdbeAddOp(v, OP_MemStore, memRowid, 1);
    addr1 = sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0);
    sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
    addr2 = sqlite3VdbeAddOp(v, OP_NotExists, iDest, 0);
    sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, 
                      "PRIMARY KEY must be unique", P3_STATIC);
    sqlite3VdbeJumpHere(v, addr2);
    autoIncStep(pParse, counterMem);
  }else{
    addr1 = sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0);
  }
  sqlite3VdbeAddOp(v, OP_RowData, iSrc, 0);
  sqlite3VdbeOp3(v, OP_Insert, iDest, OPFLAG_NCHANGE|OPFLAG_LASTROWID,
                    pDest->zName, 0);
  sqlite3VdbeAddOp(v, OP_Next, iSrc, addr1);
  autoIncEnd(pParse, iDbDest, pDest, counterMem);
  for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
    for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){

Changes to test/speed2.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
107
108
109
110
111
112
113
114
























115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
...
138
139
140
141
142
143
144
145









































146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is measuring executing speed.
#
# $Id: speed2.test,v 1.3 2007/03/27 12:04:06 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Set a uniform random seed
expr srand(0)
................................................................................
#
set sql {}
for {set i 0} {$i<50} {incr i} {
  set lwr [expr {$i*100}]
  set upr [expr {($i+10)*100}]
  append sql "SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr;"
}
speed_trial speed2-select1 [expr {50*50000}] row $sql

























# 50 SELECTs on an LIKE comparison.  There is no index so a full
# table scan is required.
#
set sql {}
for {set i 0} {$i<50} {incr i} {
  append sql \
    "SELECT count(*), avg(b) FROM t1 WHERE c LIKE '%[number_name $i]%';"
}
speed_trial speed2-select2 [expr {50*50000}] row $sql

# Create indices
#
db eval BEGIN
speed_trial speed2-createidx 150000 row {
  CREATE INDEX i1a ON t1(a);
  CREATE INDEX i1b ON t1(b);
................................................................................
#
set sql {}
for {set i 0} {$i<5000} {incr i} {
  set lwr [expr {$i*100}]
  set upr [expr {($i+10)*100}]
  append sql "SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr;"
}
speed_trial speed2-select3 5000 stmt $sql










































# 100000 random SELECTs against rowid.
#
set sql {}
for {set i 1} {$i<=100000} {incr i} {
  set id [expr {int(rand()*50000)+1}]
  append sql "SELECT c=='hi' FROM t1 WHERE rowid=$id;\n"
}
speed_trial speed2-select4 100000 row $sql

# 100000 random SELECTs against a unique indexed column.
#
set sql {}
for {set i 1} {$i<=100000} {incr i} {
  set id [expr {int(rand()*50000)+1}]
  append sql "SELECT c FROM t1 WHERE a=$id;"
}
speed_trial speed2-select5 100000 row $sql

# 50000 random SELECTs against an indexed column text column
#
set sql {}
db eval {SELECT c FROM t1 ORDER BY random() LIMIT 50000} {
  append sql "SELECT c FROM t1 WHERE c='$c';"
}
speed_trial speed2-select6 50000 row $sql

# Vacuum
speed_trial speed2-vacuum 100000 row VACUUM

# 5000 updates of ranges where the field being compared is indexed.
#
set sql {}
for {set i 0} {$i<5000} {incr i} {
  set lwr [expr {$i*2}]
  set upr [expr {($i+1)*2}]







|







 







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









|







 







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








|








|







|
<
<
<







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
...
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236



237
238
239
240
241
242
243
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is measuring executing speed.
#
# $Id: speed2.test,v 1.4 2007/03/28 18:04:10 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Set a uniform random seed
expr srand(0)
................................................................................
#
set sql {}
for {set i 0} {$i<50} {incr i} {
  set lwr [expr {$i*100}]
  set upr [expr {($i+10)*100}]
  append sql "SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr;"
}
speed_trial speed2-select1a [expr {50*50000}] row $sql

# 50 SELECTs on an LIKE comparison.  There is no index so a full
# table scan is required.
#
set sql {}
for {set i 0} {$i<50} {incr i} {
  append sql \
    "SELECT count(*), avg(b) FROM t1 WHERE c LIKE '%[number_name $i]%';"
}
speed_trial speed2-select2a [expr {50*50000}] row $sql

# Vacuum
speed_trial speed2-vacuum1 100000 row VACUUM

# 50 SELECTs on an integer comparison.  There is no index so
# a full table scan is required.
#
set sql {}
for {set i 0} {$i<50} {incr i} {
  set lwr [expr {$i*100}]
  set upr [expr {($i+10)*100}]
  append sql "SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr;"
}
speed_trial speed2-select1b [expr {50*50000}] row $sql

# 50 SELECTs on an LIKE comparison.  There is no index so a full
# table scan is required.
#
set sql {}
for {set i 0} {$i<50} {incr i} {
  append sql \
    "SELECT count(*), avg(b) FROM t1 WHERE c LIKE '%[number_name $i]%';"
}
speed_trial speed2-select2b [expr {50*50000}] row $sql

# Create indices
#
db eval BEGIN
speed_trial speed2-createidx 150000 row {
  CREATE INDEX i1a ON t1(a);
  CREATE INDEX i1b ON t1(b);
................................................................................
#
set sql {}
for {set i 0} {$i<5000} {incr i} {
  set lwr [expr {$i*100}]
  set upr [expr {($i+10)*100}]
  append sql "SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr;"
}
speed_trial speed2-select3a 5000 stmt $sql

# 100000 random SELECTs against rowid.
#
set sql {}
for {set i 1} {$i<=100000} {incr i} {
  set id [expr {int(rand()*50000)+1}]
  append sql "SELECT c=='hi' FROM t1 WHERE rowid=$id;\n"
}
speed_trial speed2-select4a 100000 row $sql

# 100000 random SELECTs against a unique indexed column.
#
set sql {}
for {set i 1} {$i<=100000} {incr i} {
  set id [expr {int(rand()*50000)+1}]
  append sql "SELECT c FROM t1 WHERE a=$id;"
}
speed_trial speed2-select5a 100000 row $sql

# 50000 random SELECTs against an indexed column text column
#
set sql {}
db eval {SELECT c FROM t1 ORDER BY random() LIMIT 50000} {
  append sql "SELECT c FROM t1 WHERE c='$c';"
}
speed_trial speed2-select6a 50000 row $sql

# Vacuum
speed_trial speed2-vacuum2 100000 row VACUUM


# 5000 SELECTs on an integer comparison where the integer is
# indexed.
#
set sql {}
for {set i 0} {$i<5000} {incr i} {
  set lwr [expr {$i*100}]
  set upr [expr {($i+10)*100}]
  append sql "SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr;"
}
speed_trial speed2-select3b 5000 stmt $sql

# 100000 random SELECTs against rowid.
#
set sql {}
for {set i 1} {$i<=100000} {incr i} {
  set id [expr {int(rand()*50000)+1}]
  append sql "SELECT c=='hi' FROM t1 WHERE rowid=$id;\n"
}
speed_trial speed2-select4b 100000 row $sql

# 100000 random SELECTs against a unique indexed column.
#
set sql {}
for {set i 1} {$i<=100000} {incr i} {
  set id [expr {int(rand()*50000)+1}]
  append sql "SELECT c FROM t1 WHERE a=$id;"
}
speed_trial speed2-select5b 100000 row $sql

# 50000 random SELECTs against an indexed column text column
#
set sql {}
db eval {SELECT c FROM t1 ORDER BY random() LIMIT 50000} {
  append sql "SELECT c FROM t1 WHERE c='$c';"
}
speed_trial speed2-select6b 50000 row $sql




# 5000 updates of ranges where the field being compared is indexed.
#
set sql {}
for {set i 0} {$i<5000} {incr i} {
  set lwr [expr {$i*2}]
  set upr [expr {($i+1)*2}]