Re: [sqlite] DELETE extremely slow (.expert command)

2019-11-02 Thread Thomas Kurz
> It would/should have told you immediately that you needed those two 
> additional indexes, I should think.

Unfortunately not. Someone told me about ".expert" some time ago and it's 
indeed helpful for me because I never know what indexes to create and why. But 
for this database everything seemed ok:

SQLite version 3.30.1 2019-10-10 20:19:45
Enter ".help" for usage hints.
sqlite> pragma foreign_keys=on;
sqlite> pragma foreign_keys;
1
sqlite> .expert
sqlite> delete from dataset;
(no new indexes)

(null)
sqlite>

___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow (.expert command)

2019-11-02 Thread Keith Medcalf

On Friday, 1 November, 2019 14:52, Thomas Kurz  wrote:

>That's it!!! You're a genius! Thank you very very much!

>Run Time: real 8.290 user 3.25 sys 1.906250

I believe that the SQLite3 CLI has a command .expert that you can use to turn 
on assistance to tell you if the next executed SQL statement will benefit from 
the creation of an index.  I forgot all about this command or even when it was 
added (it is an experimental feature).  It would/should have told you 
immediately that you needed those two additional indexes, I should think.

eg:

sqlite> create table x(a,b);
sqlite> create table y(b,c);
sqlite> .expert
sqlite> select a, x.b, c from x,y where x.b == y.b;
CREATE INDEX y_idx_0062 ON y(b);

SCAN TABLE x (~1048576 rows)
SEARCH TABLE y USING INDEX y_idx_0062 (b=?) (~10 rows)

sqlite>

>- Original Message -
>From: Keith Medcalf 
>To: SQLite mailing list 
>Sent: Friday, November 1, 2019, 18:07:51
>Subject: [sqlite] DELETE extremely slow
>
>One of your triggers requires and index on item(nameid) and there is no
>index on item(nameid).
>Hence it is doing a table scan to find the rows matching this trigger.
>That is why the plan has multiple "SCAN item" in it.




-- 
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.



___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-11-01 Thread Simon Slavin
On 1 Nov 2019, at 10:11pm, Keith Medcalf  wrote:

> Just run ".schema" or ".schema --indent"

But there's no need, since I think the problem has been solved, right ?

It came down to lack of indexes.  Which is consistent with the times and 
EXPLAIN QUERY PLANs posted.
___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-11-01 Thread Keith Medcalf

On Friday, 1 November, 2019 16:04, Thomas Kurtz wrote:

> The database schema is not a secret. If it helps, I can post it, that's
> no problem. Is it enough to run ".dump" on a database without data?

Just run ".schema" or ".schema --indent" which will output only the schema 
definitions and not the data (if any).  The extra --indent will attempt to 
format the output so it is more readable if you didn't format the SQL for 
readability when creating the database.

-- 
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.



___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-11-01 Thread Thomas Kurz
The database schema is not a secret. If it helps, I can post it, that's no 
problem. Is it enough to run ".dump" on a database without data?

- Original Message - 
From: Keith Medcalf 
To: SQLite mailing list 
Sent: Friday, November 1, 2019, 22:57:02
Subject: [sqlite] DELETE extremely slow


On Friday, 1 November, 2019 15:12, Simon Slavin  wrote:

>So the slow-down in the DELETE FROM command is caused by a TRIGGER, but
>there are no TRIGGERs on DELETE ?  I don't understand that.  Can someone
>explain, please ?

The code indicates that they are AFTER DELETE so presumably they are triggers, 
though they are fkey.abort and .abort, so they may be also the result of the 
implementation of ON DELETE conditions, which are internally implemented by 
sub-programs and cannot really be distinguished from triggers without seeing 
the full schema.  You might be able to tell if explain comments were enabled at 
compile time (SQLITE_ENABLE_EXPLAIN_COMMENTS), though I can't really say 
whether the extra comments would make it obvious or not without being able to 
see the actual schema or doing a more detailed analysis of the VDBE code.

Foreign key constraints are processed in-line since the default condition is to 
abort/rollback the entire statement only if the fkey violation count is not 
zero at the end of the statement execution.  If you have ON conditions attached 
to the foreign key constraint, they are implemented by a sub-program called 
after the processing of each row rather than inline.  This means, for example, 
that if you have ON DELETE RESTRICT specified against a foreign key constraint 
that a statement which has no violations will effectively be "half as 
efficient" as one that does not have ON DELETE RESTRICT because extra 
constraint will be implemented as a sub-program that will re-check the 
constraint during statement execution so that an immediate ABORT can be raised 
... or at least I think that is how it is implemented.  The same applies for ON 
... CASCADE or ON ... SET NULL which must be implemented as a sub-program run 
per-row and is not easily distinguishable from a trigger which implements the 
same functionality.

-- 
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.



___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-11-01 Thread Keith Medcalf

On Friday, 1 November, 2019 15:12, Simon Slavin  wrote:

>So the slow-down in the DELETE FROM command is caused by a TRIGGER, but
>there are no TRIGGERs on DELETE ?  I don't understand that.  Can someone
>explain, please ?

The code indicates that they are AFTER DELETE so presumably they are triggers, 
though they are fkey.abort and .abort, so they may be also the result of the 
implementation of ON DELETE conditions, which are internally implemented by 
sub-programs and cannot really be distinguished from triggers without seeing 
the full schema.  You might be able to tell if explain comments were enabled at 
compile time (SQLITE_ENABLE_EXPLAIN_COMMENTS), though I can't really say 
whether the extra comments would make it obvious or not without being able to 
see the actual schema or doing a more detailed analysis of the VDBE code.

Foreign key constraints are processed in-line since the default condition is to 
abort/rollback the entire statement only if the fkey violation count is not 
zero at the end of the statement execution.  If you have ON conditions attached 
to the foreign key constraint, they are implemented by a sub-program called 
after the processing of each row rather than inline.  This means, for example, 
that if you have ON DELETE RESTRICT specified against a foreign key constraint 
that a statement which has no violations will effectively be "half as 
efficient" as one that does not have ON DELETE RESTRICT because extra 
constraint will be implemented as a sub-program that will re-check the 
constraint during statement execution so that an immediate ABORT can be raised 
... or at least I think that is how it is implemented.  The same applies for ON 
... CASCADE or ON ... SET NULL which must be implemented as a sub-program run 
per-row and is not easily distinguishable from a trigger which implements the 
same functionality.

-- 
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.



___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-11-01 Thread Simon Slavin
So the slow-down in the DELETE FROM command is caused by a TRIGGER, but there 
are no TRIGGERs on DELETE ?  I don't understand that.  Can someone explain, 
please ?
___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-11-01 Thread Keith Medcalf

On Thursday, 31 October, 2019 16:54, Thomas Kurz :

>I did it again, same file:

>SQLite version 3.30.1 2019-10-10 20:19:45
>Enter ".help" for usage hints.
>sqlite> pragma foreign_keys=on;
>sqlite> .timer on
>sqlite> delete from dataset;
>Run Time: real 5249.891 user 2412.812500 sys 2606.531250

Well, this indicates only 5% idle time, so it is much better.  However, the 
process is spending a *HUGE* amount of time in the OS (sys), about half the 
elapsed time.  This indicates that I/O thrashing is still occurring.

In the CLI the command ".stats on" will output a bunch of execution statistics 
after executing a command.  Included in those are the Page cache 
hits/misses/writes/spills.  The hit rate (hits/(hits+misses)) is probably very 
low and the miss rate (misses/(hits+misses)) very high indicating I/O thrashing 
to the underlying OS (which will be reflected by increased sys time).

-- 
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.



___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-11-01 Thread Thomas Kurz
Yes, there are triggers. I didn't post them because I didn't see any 
correlation to the DELETE query as they are only INSERT and UPDATE triggers:

CREATE TRIGGER item_inserted AFTER INSERT ON item BEGIN UPDATE trace SET typeid 
= (SELECT id FROM "type" WHERE name = 'modified') WHERE trace.id = new.traceid; 
END
CREATE TRIGGER item_modified AFTER UPDATE OF traceid, freq, value, noiseflag ON 
item BEGIN UPDATE trace SET typeid = (SELECT id FROM "type" WHERE name = 
'modified') WHERE trace.id IN (old.traceid, new.traceid); END
CREATE TRIGGER meta_global_insert INSTEAD OF INSERT ON meta_global FOR EACH ROW 
BEGIN INSERT INTO metadata (parameter, value) VALUES (NEW.parameter, 
NEW.value); END
CREATE TRIGGER meta_global_update INSTEAD OF UPDATE OF parameter, value ON 
meta_global BEGIN UPDATE metadata SET parameter=NEW.parameter, value=NEW.value 
WHERE id=OLD.id AND datasetid IS NULL; END
CREATE TRIGGER meta_dataset_insert INSTEAD OF INSERT ON meta_dataset FOR EACH 
ROW WHEN NEW.datasetid IS NOT NULL BEGIN INSERT INTO metadata (parameter, 
value, datasetid) VALUES (NEW.parameter, NEW.value, NEW.datasetid); END
CREATE TRIGGER meta_dataset_update INSTEAD OF UPDATE OF datasetid, parameter, 
value ON meta_dataset WHEN NEW.datasetid IS NOT NULL BEGIN UPDATE metadata SET 
datasetid=NEW.datasetid, parameter=NEW.parameter, value=NEW.value WHERE 
id=OLD.id AND traceid IS NULL; END
CREATE TRIGGER meta_trace_insert INSTEAD OF INSERT ON meta_trace FOR EACH ROW 
WHEN NEW.traceid IS NOT NULL BEGIN INSERT INTO metadata (parameter, value, 
datasetid, traceid) SELECT NEW.parameter, NEW.value, datasetid, NEW.traceid 
FROM trace WHERE id=NEW.traceid; END
CREATE TRIGGER meta_trace_update INSTEAD OF UPDATE OF traceid, parameter, value 
ON meta_trace WHEN NEW.traceid IS NOT NULL BEGIN UPDATE metadata SET 
datasetid=(SELECT datasetid FROM trace WHERE id=NEW.traceid), 
traceid=NEW.traceid, parameter=NEW.parameter, value=NEW.value WHERE id=OLD.id 
AND itemid IS NULL; END
CREATE TRIGGER meta_item_insert INSTEAD OF INSERT ON meta_item FOR EACH ROW 
WHEN NEW.itemid IS NOT NULL BEGIN INSERT INTO metadata (parameter, value, 
datasetid, traceid, traceid) SELECT NEW.parameter, NEW.value, t.datasetid, 
t.id, NEW.itemid FROM itemid i LEFT JOIN trace t ON i.traceid=t.id WHERE 
id=NEW.itemid; END
CREATE TRIGGER meta_item_update INSTEAD OF UPDATE OF itemid, parameter, value 
ON meta_item WHEN NEW.itemid IS NOT NULL BEGIN UPDATE metadata SET 
datasetid=(SELECT t.datasetid FROM item i LEFT JOIN trace t ON i.traceid=t.id 
WHERE t.id=NEW.itemid), traceid=(SELECT traceid FROM item WHERE id=NEW.itemid), 
itemid=NEW.itemid, parameter=NEW.parameter, value=NEW.value WHERE id=OLD.id; END


- Original Message - 
From: David Raymond 
To: SQLite mailing list 
Sent: Friday, November 1, 2019, 17:27:27
Subject: [sqlite] DELETE extremely slow

Looks like you have triggers going on there. You only gave us the table and 
index definitions. What are the on delete triggers you have?


-Original Message-
From: sqlite-users  On Behalf Of 
Thomas Kurz
Sent: Thursday, October 31, 2019 6:54 PM
To: SQLite mailing list 
Subject: Re: [sqlite] DELETE extremely slow

>  Do you have memory to run this in?  Have you increased the sqlite cache size 
> because that looks (to me) an awful lot like I/O thrashing ...

Sorry to disappoint you, Keith and Simon, but in all cases the database file 
has been located on a ramdisk. It's only about 50 MB in size, btw. 

> SQLite runs on the local machine. While MariaDB is client-server, so the 
> delete effectively runs on the server.

Yes and no. Of curse, I had MariaDB run on the same machine, and its data files 
had been stored on the same ramdisk.

> How much of the 88 minutes is "waiting" time?

I did it again, same file:

SQLite version 3.30.1 2019-10-10 20:19:45
Enter ".help" for usage hints.
sqlite> pragma foreign_keys=on;
sqlite> .timer on
sqlite> delete from dataset;
Run Time: real 5249.891 user 2412.812500 sys 2606.531250

> You haven't shown the "explain query plan" Keith asked for

Is the beginning of it enough or do I have to repeat the entire DELETE? Here is 
the output which I canceled after some seconds:

QUERY PLAN
|--SCAN TABLE dataset
|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_04 (datasetid=?)
|--SEARCH TABLE trace USING COVERING INDEX trace_idx_03 (datasetid=?)
|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_04 (datasetid=?)
|--SCAN TABLE item
|--SEARCH TABLE trace USING COVERING INDEX trace_idx_03 (datasetid=?)
|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_03 (traceid=?)
|--SEARCH TABLE item USING COVERING INDEX item_idx_01 (traceid=?)
|--SCAN TABLE item
|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_03 (traceid=?)
|--SCAN TABLE item
|--SEARCH TABLE item USING COVERING INDEX item_idx_01 (traceid=?)
|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_06 (itemid=?)
|--

Re: [sqlite] DELETE extremely slow

2019-11-01 Thread Thomas Kurz
That's it!!! You're a genius! Thank you very very much!

Run Time: real 8.290 user 3.25 sys 1.906250

- Original Message - 
From: Keith Medcalf 
To: SQLite mailing list 
Sent: Friday, November 1, 2019, 18:07:51
Subject: [sqlite] DELETE extremely slow


One of your triggers requires and index on item(nameid) and there is no index 
on item(nameid).  
Hence it is doing a table scan to find the rows matching this trigger.  That is 
why the plan has multiple "SCAN item" in it.

-- 
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.



___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-11-01 Thread Keith Medcalf

One of your triggers requires and index on item(nameid) and there is no index 
on item(nameid).  
Hence it is doing a table scan to find the rows matching this trigger.  That is 
why the plan has multiple "SCAN item" in it.

-- 
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.



___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-11-01 Thread Keith Medcalf

One of your delete triggers is causing a table scan of table item.  Multiple 
scans of table item, for each row of dataset.  From the code it looks like it 
is scanning for a match on "nameid".  And there is not index on item(nameid 
...) ...

-- 
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.

>-Original Message-
>From: sqlite-users  On
>Behalf Of Thomas Kurz
>Sent: Thursday, 31 October, 2019 16:54
>To: SQLite mailing list 
>Subject: Re: [sqlite] DELETE extremely slow
>
>>  Do you have memory to run this in?  Have you increased the sqlite
>cache size because that looks (to me) an awful lot like I/O thrashing ...
>
>Sorry to disappoint you, Keith and Simon, but in all cases the database
>file has been located on a ramdisk. It's only about 50 MB in size, btw.
>
>> SQLite runs on the local machine. While MariaDB is client-server, so
>the delete effectively runs on the server.
>
>Yes and no. Of curse, I had MariaDB run on the same machine, and its data
>files had been stored on the same ramdisk.
>
>> How much of the 88 minutes is "waiting" time?
>
>I did it again, same file:
>
>SQLite version 3.30.1 2019-10-10 20:19:45
>Enter ".help" for usage hints.
>sqlite> pragma foreign_keys=on;
>sqlite> .timer on
>sqlite> delete from dataset;
>Run Time: real 5249.891 user 2412.812500 sys 2606.531250
>
>> You haven't shown the "explain query plan" Keith asked for
>
>Is the beginning of it enough or do I have to repeat the entire DELETE?
>Here is the output which I canceled after some seconds:
>
>QUERY PLAN
>|--SCAN TABLE dataset
>|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_04
>(datasetid=?)
>|--SEARCH TABLE trace USING COVERING INDEX trace_idx_03 (datasetid=?)
>|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_04
>(datasetid=?)
>|--SCAN TABLE item
>|--SEARCH TABLE trace USING COVERING INDEX trace_idx_03 (datasetid=?)
>|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_03 (traceid=?)
>|--SEARCH TABLE item USING COVERING INDEX item_idx_01 (traceid=?)
>|--SCAN TABLE item
>|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_03 (traceid=?)
>|--SCAN TABLE item
>|--SEARCH TABLE item USING COVERING INDEX item_idx_01 (traceid=?)
>|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_06 (itemid=?)
>|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_06 (itemid=?)
>`--SCAN TABLE item
>addr  opcode p1p2p3p4 p5  comment
>  -        -  --  -
>0 Init   0 30000  Start at 30
>1 Null   0 1 000  r[1]=NULL
>2 OpenRead   0 7 0 0  00  root=7 iDb=0;
>dataset
>3 Rewind 0 7 000
>4   Rowid  0 2 000  r[2]=rowid
>5   RowSetAdd  1 2 000
>rowset(1)=r[2]
>6 Next   0 4 001
>7 OpenWrite  0 7 0 3  00  root=7 iDb=0;
>dataset
>8   RowSetRead 1 29200
>r[2]=rowset(1)
>9   NotExists  0 282 1  00  intkey=r[2]
>10  Copy   2 3 000  r[3]=r[2]
>11  OpenRead   2 170 k(3,,,)02  root=17
>iDb=0; metadata_idx_04
>12  IsNull 3 18000  if r[3]==NULL
>goto 18
>13  Affinity   3 1 0 C  00
>affinity(r[3])
>14  SeekGE 2 183 1  00  key=r[3]
>15IdxGT  2 183 1  00  key=r[3]
>16FkCounter  0 1 000  fkctr[0]+=1
>17  Next   2 15000
>18  OpenRead   4 13869  0 k(2,,) 02  root=13869
>iDb=0; trace_idx_03
>19  IsNull 3 25000  if r[3]==NULL
>goto 25
>20  Affinity   3 1 0 C  00
>affinity(r[3])
>21  SeekGE 4 253 1  00  key=r[3]
>22IdxGT  4 253 1  00  key=r[3]
>23FkCounter  0 1 000  fkctr[0]+=1
>24  Next   4 22100
>25  Delete 0 1 0 dataset00
>26  Program3 0 9 program00  Call:
>fkey.abort
>27  Program3 0 10program00  Call:
>fkey.abort
>28Goto 

Re: [sqlite] DELETE extremely slow

2019-11-01 Thread David Raymond
Looks like you have triggers going on there. You only gave us the table and 
index definitions. What are the on delete triggers you have?


-Original Message-
From: sqlite-users  On Behalf Of 
Thomas Kurz
Sent: Thursday, October 31, 2019 6:54 PM
To: SQLite mailing list 
Subject: Re: [sqlite] DELETE extremely slow

>  Do you have memory to run this in?  Have you increased the sqlite cache size 
> because that looks (to me) an awful lot like I/O thrashing ...

Sorry to disappoint you, Keith and Simon, but in all cases the database file 
has been located on a ramdisk. It's only about 50 MB in size, btw. 

> SQLite runs on the local machine. While MariaDB is client-server, so the 
> delete effectively runs on the server.

Yes and no. Of curse, I had MariaDB run on the same machine, and its data files 
had been stored on the same ramdisk.

> How much of the 88 minutes is "waiting" time?

I did it again, same file:

SQLite version 3.30.1 2019-10-10 20:19:45
Enter ".help" for usage hints.
sqlite> pragma foreign_keys=on;
sqlite> .timer on
sqlite> delete from dataset;
Run Time: real 5249.891 user 2412.812500 sys 2606.531250

> You haven't shown the "explain query plan" Keith asked for

Is the beginning of it enough or do I have to repeat the entire DELETE? Here is 
the output which I canceled after some seconds:

QUERY PLAN
|--SCAN TABLE dataset
|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_04 (datasetid=?)
|--SEARCH TABLE trace USING COVERING INDEX trace_idx_03 (datasetid=?)
|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_04 (datasetid=?)
|--SCAN TABLE item
|--SEARCH TABLE trace USING COVERING INDEX trace_idx_03 (datasetid=?)
|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_03 (traceid=?)
|--SEARCH TABLE item USING COVERING INDEX item_idx_01 (traceid=?)
|--SCAN TABLE item
|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_03 (traceid=?)
|--SCAN TABLE item
|--SEARCH TABLE item USING COVERING INDEX item_idx_01 (traceid=?)
|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_06 (itemid=?)
|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_06 (itemid=?)
`--SCAN TABLE item
addr  opcode p1p2p3p4 p5  comment  
  -        -  --  -
0 Init   0 30000  Start at 30  
1 Null   0 1 000  r[1]=NULL
2 OpenRead   0 7 0 0  00  root=7 iDb=0; dataset
3 Rewind 0 7 000   
4   Rowid  0 2 000  r[2]=rowid   
5   RowSetAdd  1 2 000  rowset(1)=r[2]
6 Next   0 4 001   
7 OpenWrite  0 7 0 3  00  root=7 iDb=0; dataset
8   RowSetRead 1 29200  r[2]=rowset(1)
9   NotExists  0 282 1  00  intkey=r[2]  
10  Copy   2 3 000  r[3]=r[2]
11  OpenRead   2 170 k(3,,,)02  root=17 iDb=0; 
metadata_idx_04
12  IsNull 3 18000  if r[3]==NULL goto 
18
13  Affinity   3 1 0 C  00  affinity(r[3])
14  SeekGE 2 183 1  00  key=r[3] 
15IdxGT  2 183 1  00  key=r[3] 
16FkCounter  0 1 000  fkctr[0]+=1  
17  Next   2 15000   
18  OpenRead   4 13869  0 k(2,,) 02  root=13869 iDb=0; 
trace_idx_03
19  IsNull 3 25000  if r[3]==NULL goto 
25
20  Affinity   3 1 0 C  00  affinity(r[3])
21  SeekGE 4 253 1  00  key=r[3] 
22IdxGT  4 253 1  00  key=r[3] 
23FkCounter  0 1 000  fkctr[0]+=1  
24  Next   4 22100   
25  Delete 0 1 0 dataset00   
26  Program3 0 9 program00  Call: fkey.abort
27  Program3 0 10program00  Call: fkey.abort
28Goto   0 8 000   
29Halt   0 0 000   
30Transaction0 1 400  01  usesStmtJournal=0
31Goto   0 1 000   
0 Init   0 1 000  Start at 1; Start: 
.abort (AFTER DELETE ON dataset)
1 Null   0 1 000  r[1]=NULL
2 OpenRe

Re: [sqlite] DELETE extremely slow

2019-11-01 Thread Thomas Kurz
>  Do you have memory to run this in?  Have you increased the sqlite cache size 
> because that looks (to me) an awful lot like I/O thrashing ...

Sorry to disappoint you, Keith and Simon, but in all cases the database file 
has been located on a ramdisk. It's only about 50 MB in size, btw. 

> SQLite runs on the local machine. While MariaDB is client-server, so the 
> delete effectively runs on the server.

Yes and no. Of curse, I had MariaDB run on the same machine, and its data files 
had been stored on the same ramdisk.

> How much of the 88 minutes is "waiting" time?

I did it again, same file:

SQLite version 3.30.1 2019-10-10 20:19:45
Enter ".help" for usage hints.
sqlite> pragma foreign_keys=on;
sqlite> .timer on
sqlite> delete from dataset;
Run Time: real 5249.891 user 2412.812500 sys 2606.531250

> You haven't shown the "explain query plan" Keith asked for

Is the beginning of it enough or do I have to repeat the entire DELETE? Here is 
the output which I canceled after some seconds:

QUERY PLAN
|--SCAN TABLE dataset
|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_04 (datasetid=?)
|--SEARCH TABLE trace USING COVERING INDEX trace_idx_03 (datasetid=?)
|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_04 (datasetid=?)
|--SCAN TABLE item
|--SEARCH TABLE trace USING COVERING INDEX trace_idx_03 (datasetid=?)
|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_03 (traceid=?)
|--SEARCH TABLE item USING COVERING INDEX item_idx_01 (traceid=?)
|--SCAN TABLE item
|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_03 (traceid=?)
|--SCAN TABLE item
|--SEARCH TABLE item USING COVERING INDEX item_idx_01 (traceid=?)
|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_06 (itemid=?)
|--SEARCH TABLE metadata USING COVERING INDEX metadata_idx_06 (itemid=?)
`--SCAN TABLE item
addr  opcode p1p2p3p4 p5  comment  
  -        -  --  -
0 Init   0 30000  Start at 30  
1 Null   0 1 000  r[1]=NULL
2 OpenRead   0 7 0 0  00  root=7 iDb=0; dataset
3 Rewind 0 7 000   
4   Rowid  0 2 000  r[2]=rowid   
5   RowSetAdd  1 2 000  rowset(1)=r[2]
6 Next   0 4 001   
7 OpenWrite  0 7 0 3  00  root=7 iDb=0; dataset
8   RowSetRead 1 29200  r[2]=rowset(1)
9   NotExists  0 282 1  00  intkey=r[2]  
10  Copy   2 3 000  r[3]=r[2]
11  OpenRead   2 170 k(3,,,)02  root=17 iDb=0; 
metadata_idx_04
12  IsNull 3 18000  if r[3]==NULL goto 
18
13  Affinity   3 1 0 C  00  affinity(r[3])
14  SeekGE 2 183 1  00  key=r[3] 
15IdxGT  2 183 1  00  key=r[3] 
16FkCounter  0 1 000  fkctr[0]+=1  
17  Next   2 15000   
18  OpenRead   4 13869  0 k(2,,) 02  root=13869 iDb=0; 
trace_idx_03
19  IsNull 3 25000  if r[3]==NULL goto 
25
20  Affinity   3 1 0 C  00  affinity(r[3])
21  SeekGE 4 253 1  00  key=r[3] 
22IdxGT  4 253 1  00  key=r[3] 
23FkCounter  0 1 000  fkctr[0]+=1  
24  Next   4 22100   
25  Delete 0 1 0 dataset00   
26  Program3 0 9 program00  Call: fkey.abort
27  Program3 0 10program00  Call: fkey.abort
28Goto   0 8 000   
29Halt   0 0 000   
30Transaction0 1 400  01  usesStmtJournal=0
31Goto   0 1 000   
0 Init   0 1 000  Start at 1; Start: 
.abort (AFTER DELETE ON dataset)
1 Null   0 1 000  r[1]=NULL
2 OpenRead   11170 k(3,,,)02  root=17 iDb=0; 
metadata_idx_04
3 Param  0 2 000  r[2]=old.rowid
4 IsNull 2 11000  if r[2]==NULL goto 11
5 Affinity   2 1 0 C  00  affinity(r[2])
6 SeekGE 11112 1  00  key=r[2] 
7 

Re: [sqlite] DELETE extremely slow

2019-10-31 Thread Thomas Kurz
> According to the MariaDB reference manual, it does not "do anything" with 
> references clauses on columns.

Thanks for that hint, I will try again tomorrow because I cannot say for sure 
now whether it worked correctly or not. (And I don't have that data available 
anymore.)

___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-10-31 Thread Keith Medcalf

On Thursday, 31 October, 2019 03:51, Thomas Kurz  wrote:

>I experimentally imported the same data into a MariaDB database and tried
>the same operation there (without paying attention to creating any
>indexes, etc.). It takes only a few seconds there.

According to the MariaDB reference manual, it does not "do anything" with 
references clauses on columns.  They are merely for entertainment purposes.  
You have to use the table constraint syntax to declare enforceable foreign key 
constraints, which means you cannot use the same CREATE TABLE syntax for 
MariaDB as for SQLite3.

From https://mariadb.com/kb/en/library/create-table/

Note: MariaDB accepts the REFERENCES clause in ALTER TABLE and CREATE TABLE 
column definitions, but that syntax does nothing. MariaDB simply parses it 
without returning any error or warning, for compatibility with other DBMS's. 
Before MariaDB 10.2.1 this was also true for CHECK constraints. Only the syntax 
for indexes described below creates foreign keys.

-- 
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.



___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-10-31 Thread Keith Medcalf

On Thursday, 31 October, 2019 10:52, Simon Slavin  wrote:

>On 31 Oct 2019, at 4:29pm, Keith Medcalf  wrote:

>> If the elapsed time is much greater than the sum of user+sys time then
>> I would suspect it is still I/O thrashing (or the machine is really busy
>> doing something else -- those original timings represent only a 57%
>> process dispatch rate, which is pretty low).

> I'm betting it's a rotating hard disk with a slow spin speed, and most of
> the time is spent waiting for the disk to be in the right place.

> As Dominique Devienne spotted, there is now some doubt about the
> comparative figure.  Was the MariaDB filespace hosted on this same hard
> disk ?

While nice, that is irrelevant.  MariaDB is a client/server database so it 
probably uses a database cache that is considerably larger by default than the 
SQLite default.  The SQLite default cache is 2 MB which is 500 pages at the 
default page size of 4K.

>The original post had

>> The largest table contains about 230'000 entries.

> Five tables and eleven indexes.  Sixteen pages and sixteen page indexes.
> Even if you think that all the required indexes for FOREIGN KEY lookup
> are now available, I think that 88 minutes is still longer than SQLite
> should take for anything but a slow disk.

That is why I asked about the cache_size.  If the cache_size has not been 
increased from the default then a large operation will be thrashing and 
spilling pages sto perform a large operation like that.  For I/O intensive 
operations the size of SQLite's page cache makes a huge difference, far more 
than an adequate filesystem or block cache in reducing I/O.

-- 
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.



___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-10-31 Thread Simon Slavin
On 31 Oct 2019, at 4:29pm, Keith Medcalf  wrote:

> If the elapsed time is much greater than the sum of user+sys time then I 
> would suspect it is still I/O thrashing (or the machine is really busy doing 
> something else -- those original timings represent only a 57% process 
> dispatch rate, which is pretty low).

I'm betting it's a rotating hard disk with a slow spin speed, and most of the 
time is spent waiting for the disk to be in the right place.

As Dominique Devienne spotted, there is now some doubt about the comparative 
figure.  Was the MariaDB filespace hosted on this same hard disk ?

The original post had

> The largest table contains about 230'000 entries.

Five tables and eleven indexes.  Sixteen pages and sixteen page indexes.  Even 
if you think that all the required indexes for FOREIGN KEY lookup are now 
available, I think that 88 minutes is still longer than SQLite should take for 
anything but a slow disk.
___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-10-31 Thread Keith Medcalf

On Thursday, 31 October, 2019 10:01, Dominique Devienne  
wrote:

>On Thu, Oct 31, 2019 at 4:10 PM Thomas Kurz  wrote:

>> Yes, but I'd expect that MariaDB has to do the same, but takes clearly
>> less than 1 minute instead of 88 minutes... :confused:

>Are we comparing apples to oranges here?

>SQLite runs on the local machine. While MariaDB is client-server, so the
>delete effectively runs on the server.
>Is your MariaDB server local to the same machine you're running SQLite
>on?
>Are both using the same local disks? (as opposed to networked and/or
>different disks)

>Still can't account for 88 minutes though.

Well, 88 minutes is a lot better than 56 hours, of which 24 hours was "waiting" 
time.  How much of the 88 minutes is "waiting" time?  If the elapsed time is 
much greater than the sum of user+sys time then I would suspect it is still I/O 
thrashing (or the machine is really busy doing something else -- those original 
timings represent only a 57% process dispatch rate, which is pretty low).

>You haven't shown the "explain query plan" Keith asked for, which would
>help understand what's going on here.

Well, having added the missing index I doubt that there is anything else to be 
found there.

-- 
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.




___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-10-31 Thread Dominique Devienne
On Thu, Oct 31, 2019 at 4:10 PM Thomas Kurz  wrote:

> Yes, but I'd expect that MariaDB has to do the same, but takes clearly
> less than 1 minute instead of 88 minutes... :confused:
>

Are we comparing apples to oranges here?

SQLite runs on the local machine. While MariaDB is client-server, so the
delete effectively runs on the server.
Is your MariaDB server local to the same machine you're running SQLite on?
Are both using the same local disks? (as opposed to networked and/or
different disks)

Still can't account for 88 minutes though.
You haven't shown the "explain query plan" Keith asked for, which would
help understand what's going on here.
See https://www.sqlite.org/eqp.html
___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-10-31 Thread Keith Medcalf
>pragma foreign_keys=on;
>pragma journal_mode=wal;
>.timer on
>delete from dataset;
>--> Run Time: real 197993.218 user 53015.593750 sys 54056.546875

Wow.  That is 14 hours each of System and User time and then and additional 24 
hours of "waiting for something to happen" time.  Do you have memory to run 
this in?  Have you increased the sqlite cache size because that looks (to me) 
an awful lot like I/O thrashing ...

-- 
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.



___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-10-31 Thread Simon Slavin
On 31 Oct 2019, at 3:09pm, Thomas Kurz  wrote:

> The result of "DELETE FROM dataset" is now 88 minutes

That still seems wrong.  I hope the list can help you track down what's going 
on.
___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-10-31 Thread David Raymond
It's not gonna account for 88 minutes, but out of curiosity is there a way to 
separately report the "delete and commit" time from the "dang this WAL needs to 
be checkpointed now" time?


-Original Message-
From: sqlite-users  On Behalf Of 
Thomas Kurz
Sent: Thursday, October 31, 2019 11:10 AM
To: SQLite mailing list 
Subject: Re: [sqlite] DELETE extremely slow

> Something is wrong.  If you did multiple commands like
>
> DELETE FROM MyTable;
>
> to your child tables, they should be fast.  Have you run an integrity check ?

I created a new database now, added the missing index "trace(datasetid)" as 
suggested by Keith.

The result of "DELETE FROM dataset" is now 88 minutes, which of course is 
better than before where it took hours, but not nearly as quick as I'd expect...

@Warren:
> Is that command representative of actual use, or are you deleting all rows 
> just for the purpose of benchmarking?

Usually I want to delete only several datasets, but not all. I left out the 
where-clause for simplification now.

@Keith:
> and in the face of enforced foreign key constraints will always delete the 
> rows one by each even if dependent (child) tables have no rows.

Yes, but I'd expect that MariaDB has to do the same, but takes clearly less 
than 1 minute instead of 88 minutes... :confused:

___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-10-31 Thread Thomas Kurz
> Something is wrong.  If you did multiple commands like
>
> DELETE FROM MyTable;
>
> to your child tables, they should be fast.  Have you run an integrity check ?

I created a new database now, added the missing index "trace(datasetid)" as 
suggested by Keith.

The result of "DELETE FROM dataset" is now 88 minutes, which of course is 
better than before where it took hours, but not nearly as quick as I'd expect...

@Warren:
> Is that command representative of actual use, or are you deleting all rows 
> just for the purpose of benchmarking?

Usually I want to delete only several datasets, but not all. I left out the 
where-clause for simplification now.

@Keith:
> and in the face of enforced foreign key constraints will always delete the 
> rows one by each even if dependent (child) tables have no rows.

Yes, but I'd expect that MariaDB has to do the same, but takes clearly less 
than 1 minute instead of 88 minutes... :confused:

___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-10-31 Thread David Raymond
"Four observations that may (or may not) explain the problem:
- dataset.id declared "unique": useless since the primary key is unique 
by definition but it may create an index (not checked). A PK is not 
"more unique" if an additional "unique" constraint is declared."

Declaring it as both "primary key" and "unique" makes an extra (duplicate) 
index, yes. With the added uniqueness checking on the duplicate index as well.



SQLite version 3.29.0 2019-07-10 17:32:03
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.

sqlite> create table foo1 (pk integer primary key);

sqlite> create table foo2(pk integer primary key unique);

sqlite> select * from sqlite_master;
type|name|tbl_name|rootpage|sql
table|foo1|foo1|2|CREATE TABLE foo1 (pk integer primary key)
table|foo2|foo2|3|CREATE TABLE foo2(pk integer primary key unique)
index|sqlite_autoindex_foo2_1|foo2|4|

sqlite> explain insert into foo1 values (?);
addr  opcode p1p2p3p4 p5  comment
  -        -  --  -
0 Init   0 13000  Start at 13
1 OpenWrite  0 2 0 1  00  root=2 iDb=0; foo1
2 Variable   1 1 000  r[1]=parameter(1,)
3 NotNull1 5 000  if r[1]!=NULL goto 5
4 NewRowid   0 1 000  r[1]=rowid
5 MustBeInt  1 0 000
6 SoftNull   2 0 000  r[2]=NULL
7 Noop   0 0 000  uniqueness check for 
ROWID
8 NotExists  0 10100  intkey=r[1]
9 Halt   1555  2 0 foo1.pk02
10MakeRecord 2 1 3 D  00  r[3]=mkrec(r[2])
11Insert 0 3 1 foo1   31  intkey=r[1] data=r[3]
12Halt   0 0 000
13Transaction0 1 2 0  01  usesStmtJournal=0
14Goto   0 1 000

sqlite> explain insert into foo2 values (?);
addr  opcode p1p2p3p4 p5  comment
  -        -  --  -
0 Init   0 22000  Start at 22
1 OpenWrite  0 3 0 1  00  root=3 iDb=0; foo2
2 OpenWrite  1 4 0 k(1,)  00  root=4 iDb=0; 
sqlite_autoindex_foo2_1
3 Variable   1 1 000  r[1]=parameter(1,)
4 NotNull1 6 000  if r[1]!=NULL goto 6
5 NewRowid   0 1 000  r[1]=rowid
6 MustBeInt  1 0 000
7 SoftNull   2 0 000  r[2]=NULL
8 Noop   0 0 000  uniqueness check for 
ROWID
9 NotExists  0 11100  intkey=r[1]
10Halt   1555  2 0 foo2.pk02
11Affinity   2 1 0 D  00  affinity(r[2])
12Noop   0 0 000  uniqueness check for 
sqlite_autoindex_foo2_1
13SCopy  1 4 000  r[4]=r[1]; pk
14IntCopy1 5 000  r[5]=r[1]; rowid
15MakeRecord 4 2 300  r[3]=mkrec(r[4..5]); 
for sqlite_autoindex_foo2_1
16NoConflict 1 184 1  00  key=r[4]
17Halt   2067  2 0 foo2.pk02
18MakeRecord 2 1 600  r[6]=mkrec(r[2])
19IdxInsert  1 3 4 1  10  key=r[3]
20Insert 0 6 1 foo2   31  intkey=r[1] data=r[6]
21Halt   0 0 000
22Transaction0 1 2 0  01  usesStmtJournal=0
23Goto   0 1 000

sqlite>
___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-10-31 Thread Keith Medcalf

If you are deleting all the rows of a table, then you can simply truncate the 
table (SQLite will do this).  However if the table you are deleting all the 
rows from have dependent (child) tables *and* foreign key enforcement is turned 
on, then the rows have to be deleted on at a time so that the foreign key 
constraints can be checked, although if all the child tables have no rows you 
should be able to just truncate the parent.  SQLite does not perform that 
optimization and in the face of enforced foreign key constraints will always 
delete the rows one by each even if dependent (child) tables have no rows.

-- 
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.

>-Original Message-
>From: sqlite-users  On
>Behalf Of Thomas Kurz
>Sent: Thursday, 31 October, 2019 05:10
>To: SQLite mailing list 
>Subject: Re: [sqlite] DELETE extremely slow
>
>> Keith found the answer: you don't have the indexes required to make
>your FOREIGN KEYs run quickly.
>
>Thanks, I will try that.
>
>> If you DELETE FROM the child tables first, do you get fast or slow
>times ?
>
>Yes, I already tried deleting from each table individually. It's slow
>everywhere.
>
>> Thee way you're doing it involves a lot of steps as SQlite works its
>way through the parent table, deletes one row from that, and cascades
>through the other tables, looking for and deleting related rows from
>those.
>
>Ok, I might have errors in my declarations, but SQLite seems to have
>problems as well, because MariaDB (without any explicit index defintion!)
>handles the same deletion within seconds...
>
>___
>sqlite-users mailing list
>sqlite-users@mailinglists.sqlite.org
>http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users



___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-10-31 Thread Warren Young
On Oct 31, 2019, at 3:51 AM, Thomas Kurz  wrote:
> 
> delete from dataset;

Is that command representative of actual use, or are you deleting all rows just 
for the purpose of benchmarking?

I ask because if you’re going to just delete all rows in a table, it’s usually 
faster to DROP TABLE and then CREATE TABLE.

___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-10-31 Thread Simon Slavin
On 31 Oct 2019, at 11:09am, Thomas Kurz  wrote:

> Yes, I already tried deleting from each table individually. It's slow 
> everywhere.

Something is wrong.  If you did multiple commands like

DELETE FROM MyTable;

to your child tables, they should be fast.  Have you run an integrity check ?
___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-10-31 Thread Thomas Kurz
> Keith found the answer: you don't have the indexes required to make your 
> FOREIGN KEYs run quickly.

Thanks, I will try that.

> If you DELETE FROM the child tables first, do you get fast or slow times ?

Yes, I already tried deleting from each table individually. It's slow 
everywhere.

> Thee way you're doing it involves a lot of steps as SQlite works its way 
> through the parent table, deletes one row from that, and cascades through the 
> other tables, looking for and deleting related rows from those.

Ok, I might have errors in my declarations, but SQLite seems to have problems 
as well, because MariaDB (without any explicit index defintion!) handles the 
same deletion within seconds...

___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-10-31 Thread Jean-Luc Hainaut


Four observations that may (or may not) explain the problem:
- dataset.id declared "unique": useless since the primary key is unique 
by definition but it may create an index (not checked). A PK is not 
"more unique" if an additional "unique" constraint is declared..
- no "on delete <...>" on trace.datasetid; so, default "no action". Is 
it what you want?
- no index on this foreign key, hence potential full scan to identify 
children rows in "trace" (or absence thereof).
- index trace_idx_01 declared twice. Most often once is sufficient, even 
for large tables.


Jean-Luc Hainaut


Yes, please apologize, I indeed forgot to attach the table definitions:

CREATE TABLE dataset (
 id INTEGER  PRIMARY KEY AUTOINCREMENT
 UNIQUE
 NOT NULL,
 name   STRING   DEFAULT NULL
 COLLATE NOCASE,
 is_latest  BOOLEAN  NOT NULL
 DEFAULT 1,
 created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE trace (
 id INTEGER  PRIMARY KEY AUTOINCREMENT
 UNIQUE
 NOT NULL,
 name   STRING   DEFAULT NULL
 COLLATE NOCASE,
 datasetid  INTEGER  REFERENCES dataset (id)
 NOT NULL,
 quantityid INTEGER  REFERENCES quantity (id)
 NOT NULL,
 stored DATETIME DEFAULT NULL,
 created_at DATETIME NOT NULL
 DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX trace_idx_01 ON trace (
 quantityid
);

CREATE INDEX trace_idx_01 ON trace (
 quantityid
);

CREATE TABLE item (
 idINTEGER PRIMARY KEY AUTOINCREMENT
   UNIQUE
   NOT NULL,
 traceid   INTEGER REFERENCES trace (id)
   NOT NULL,
 freq  BIGINT  NOT NULL,
 value REALNOT NULL,
 noiseflag BOOLEAN DEFAULT NULL
);

CREATE INDEX item_idx_01 ON item (
 traceid
);

CREATE TABLE metadata (
 idINTEGER PRIMARY KEY AUTOINCREMENT
   UNIQUE
   NOT NULL,
 parameter STRING  NOT NULL
   COLLATE NOCASE,
 value STRING  NOT NULL
   COLLATE NOCASE,
 datasetid INTEGER DEFAULT NULL
   REFERENCES dataset (id),
 traceid   INTEGER DEFAULT NULL
   REFERENCES trace (id),
 itemidINTEGER DEFAULT NULL
   REFERENCES item (id)
);

CREATE INDEX metadata_idx_01 ON metadata (
 parameter,
 value,
 datasetid,
 traceid,
 itemid
);

CREATE INDEX metadata_idx_02 ON metadata (
 datasetid,
 traceid
);

CREATE INDEX metadata_idx_03 ON metadata (
 traceid
);

CREATE INDEX metadata_idx_04 ON metadata (
 datasetid,
 itemid
);

CREATE INDEX metadata_idx_05 ON metadata (
 traceid,
 itemid
);

CREATE INDEX metadata_idx_06 ON metadata (
 itemid
);

CREATE INDEX metadata_idx_07 ON metadata (
 datasetid,
 parameter
);

CREATE INDEX metadata_idx_08 ON metadata (
 traceid,
 parameter
);

CREATE INDEX metadata_idx_09 ON metadata (
 parameter,
 traceid
);

CREATE INDEX metadata_idx_10 ON metadata (
 parameter,
 datasetid,
 traceid,
 itemid
);

CREATE TABLE quantity (
 id INTEGER PRIMARY KEY AUTOINCREMENT
UNIQUE
NOT NULL,
 name   STRING  NOT NULL,
 unit   STRING  NOT NULL,
 sumrule[SMALLINT UNSIGNED] DEFAULT NULL,
 created_at DATETIMEDEFAULT CURRENT_TIMESTAMP,
 UNIQUE (
 name,
 unit,
 sumrule
 )
 ON CONFLICT IGNORE
);





- Original Message -
From: Dominique Devienne 
To: SQLite mailing list 
Sent: Thursday, October 31, 2019, 11:06:07
Subject: [sqlite] DELETE extremely slow

On Thu, Oct 31, 2019 at 10:57 AM Thomas Kurz  wrote:


I'm using a database with 5 hierarchically strcutured tables using foreign
keys. The largest table contains about 230'000 entries. My problem is that
deleting in this database is extremely slow:
pragma foreign_keys=on;
pragma journal_mode=wal;
.timer on
delete from dataset;
--> Run Time: real 197993.218 user 53015.593750 sys 54056.546875
I experimentally imported the same data into a MariaDB database and tried
the same operation there (without paying attention to creating any indexes,
etc.). It takes only a few seconds there.
Is there something I can check or do to improve deletion speed?


You're not describing the schema enough IMHO.
Is dataset the "top-most" table, containing the "parent" rows all other
tables references (directly or indirectly),
with all FKs having ON DELETE CASCADE?

If that's the case, without some kind of optimization in SQLite, when the

Re: [sqlite] DELETE extremely slow

2019-10-31 Thread Simon Slavin
On 31 Oct 2019, at 9:51am, Thomas Kurz  wrote:

> I'm using a database with 5 hierarchically strcutured tables using foreign 
> keys. The largest table contains about 230'000 entries. My problem is that 
> deleting in this database is extremely slow:

Keith found the answer: you don't have the indexes required to make your 
FOREIGN KEYs run quickly.  But I have a question:

If you DELETE FROM the child tables first, do you get fast or slow times ?

Thee way you're doing it involves a lot of steps as SQlite works its way 
through the parent table, deletes one row from that, and cascades through the 
other tables, looking for and deleting related rows from those.

SQLite has an optimization for DELETE FROM without a WHERE clause.  But I don't 
know if it's smart enough to realise that if you do that to a parent table, you 
can also do it to all child tables.  Or perhaps its not true and there might be 
child rows with no parent row, and SQLite is making sure it preserves them.
___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] DELETE extremely slow

2019-10-31 Thread Keith Medcalf

You have no index on trace(datasetid) ... 
You have no index on metadata(datasetid) though the compound indexes in which 
datasetid is the first element *should* be sufficent.

.eqp on or .eqp full before issuing the delete command will tell you what the 
plan is.

-- 
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.

>-Original Message-
>From: sqlite-users  On
>Behalf Of Thomas Kurz
>Sent: Thursday, 31 October, 2019 04:25
>To: SQLite mailing list 
>Subject: Re: [sqlite] DELETE extremely slow
>
>Yes, please apologize, I indeed forgot to attach the table definitions:
>
>CREATE TABLE dataset (
>id INTEGER  PRIMARY KEY AUTOINCREMENT
>UNIQUE
>NOT NULL,
>name   STRING   DEFAULT NULL
>COLLATE NOCASE,
>is_latest  BOOLEAN  NOT NULL
>DEFAULT 1,
>created_at DATETIME DEFAULT CURRENT_TIMESTAMP
>);
>
>CREATE TABLE trace (
>id INTEGER  PRIMARY KEY AUTOINCREMENT
>UNIQUE
>NOT NULL,
>name   STRING   DEFAULT NULL
>COLLATE NOCASE,
>datasetid  INTEGER  REFERENCES dataset (id)
>NOT NULL,
>quantityid INTEGER  REFERENCES quantity (id)
>NOT NULL,
>stored DATETIME DEFAULT NULL,
>created_at DATETIME NOT NULL
>DEFAULT CURRENT_TIMESTAMP
>);
>
>CREATE INDEX trace_idx_01 ON trace (
>quantityid
>);
>
>CREATE INDEX trace_idx_01 ON trace (
>quantityid
>);
>
>CREATE TABLE item (
>idINTEGER PRIMARY KEY AUTOINCREMENT
>  UNIQUE
>  NOT NULL,
>traceid   INTEGER REFERENCES trace (id)
>  NOT NULL,
>freq  BIGINT  NOT NULL,
>value REALNOT NULL,
>noiseflag BOOLEAN DEFAULT NULL
>);
>
>CREATE INDEX item_idx_01 ON item (
>traceid
>);
>
>CREATE TABLE metadata (
>idINTEGER PRIMARY KEY AUTOINCREMENT
>  UNIQUE
>  NOT NULL,
>parameter STRING  NOT NULL
>  COLLATE NOCASE,
>value STRING  NOT NULL
>  COLLATE NOCASE,
>datasetid INTEGER DEFAULT NULL
>  REFERENCES dataset (id),
>traceid   INTEGER DEFAULT NULL
>  REFERENCES trace (id),
>itemidINTEGER DEFAULT NULL
>  REFERENCES item (id)
>);
>
>CREATE INDEX metadata_idx_01 ON metadata (
>parameter,
>value,
>datasetid,
>traceid,
>itemid
>);
>
>CREATE INDEX metadata_idx_02 ON metadata (
>datasetid,
>traceid
>);
>
>CREATE INDEX metadata_idx_03 ON metadata (
>traceid
>);
>
>CREATE INDEX metadata_idx_04 ON metadata (
>datasetid,
>itemid
>);
>
>CREATE INDEX metadata_idx_05 ON metadata (
>traceid,
>itemid
>);
>
>CREATE INDEX metadata_idx_06 ON metadata (
>itemid
>);
>
>CREATE INDEX metadata_idx_07 ON metadata (
>datasetid,
>parameter
>);
>
>CREATE INDEX metadata_idx_08 ON metadata (
>traceid,
>parameter
>);
>
>CREATE INDEX metadata_idx_09 ON metadata (
>parameter,
>traceid
>);
>
>CREATE INDEX metadata_idx_10 ON metadata (
>parameter,
>datasetid,
>traceid,
>itemid
>);
>
>CREATE TABLE quantity (
>id INTEGER PRIMARY KEY AUTOINCREMENT
>   UNIQUE
>   NOT NULL,
>name   STRING  NOT NULL,
>    unit   STRING      NOT NULL,
>sumrule[SMALLINT UNSIGNED] DEFAULT NULL,
>created_at DATETIMEDEFAULT CURRENT_TIMESTAMP,
>UNIQUE (
>name,
>unit,
>sumrule
>)
>ON CONFLICT IGNORE
>);
>
>
>
>
>
>- Original Message -
>From: Dominique Devienne 
>To: SQLite mailing list 
>Sent: Thursday, October 31, 2019, 11:06:07
>Subject: [sqlite] DELETE extremely slow
>
>On Thu, Oct 31, 2019 at 10:57 AM Thomas Kurz 
>wrote:
>
>> I'm using a database with 5 hierarchically strcutured tables using
>foreign
>> keys. The largest table contains about 230'000 entries. My problem is
>that
>> deleting in this database is extremely slow:
>
>> pragma foreign_keys=on;
>> pragma journal_mode=wal;
>> .timer on
>> delete from dataset;
>> --> Run Time: real 197993.218 user 53015.593750 sys 54056.546875
>
>> I exper

Re: [sqlite] DELETE extremely slow

2019-10-31 Thread Thomas Kurz
Yes, please apologize, I indeed forgot to attach the table definitions:

CREATE TABLE dataset (
id INTEGER  PRIMARY KEY AUTOINCREMENT
UNIQUE
NOT NULL,
name   STRING   DEFAULT NULL
COLLATE NOCASE,
is_latest  BOOLEAN  NOT NULL
DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE trace (
id INTEGER  PRIMARY KEY AUTOINCREMENT
UNIQUE
NOT NULL,
name   STRING   DEFAULT NULL
COLLATE NOCASE,
datasetid  INTEGER  REFERENCES dataset (id) 
NOT NULL,
quantityid INTEGER  REFERENCES quantity (id) 
NOT NULL,
stored DATETIME DEFAULT NULL,
created_at DATETIME NOT NULL
DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX trace_idx_01 ON trace (
quantityid
);

CREATE INDEX trace_idx_01 ON trace (
quantityid
);

CREATE TABLE item (
idINTEGER PRIMARY KEY AUTOINCREMENT
  UNIQUE
  NOT NULL,
traceid   INTEGER REFERENCES trace (id) 
  NOT NULL,
freq  BIGINT  NOT NULL,
value REALNOT NULL,
noiseflag BOOLEAN DEFAULT NULL
);

CREATE INDEX item_idx_01 ON item (
traceid
);

CREATE TABLE metadata (
idINTEGER PRIMARY KEY AUTOINCREMENT
  UNIQUE
  NOT NULL,
parameter STRING  NOT NULL
  COLLATE NOCASE,
value STRING  NOT NULL
  COLLATE NOCASE,
datasetid INTEGER DEFAULT NULL
  REFERENCES dataset (id),
traceid   INTEGER DEFAULT NULL
  REFERENCES trace (id),
itemidINTEGER DEFAULT NULL
  REFERENCES item (id) 
);

CREATE INDEX metadata_idx_01 ON metadata (
parameter,
value,
datasetid,
traceid,
itemid
);

CREATE INDEX metadata_idx_02 ON metadata (
datasetid,
traceid
);

CREATE INDEX metadata_idx_03 ON metadata (
traceid
);

CREATE INDEX metadata_idx_04 ON metadata (
datasetid,
itemid
);

CREATE INDEX metadata_idx_05 ON metadata (
traceid,
itemid
);

CREATE INDEX metadata_idx_06 ON metadata (
itemid
);

CREATE INDEX metadata_idx_07 ON metadata (
datasetid,
parameter
);

CREATE INDEX metadata_idx_08 ON metadata (
traceid,
parameter
);

CREATE INDEX metadata_idx_09 ON metadata (
parameter,
traceid
);

CREATE INDEX metadata_idx_10 ON metadata (
parameter,
datasetid,
traceid,
itemid
);

CREATE TABLE quantity (
id INTEGER PRIMARY KEY AUTOINCREMENT
   UNIQUE
   NOT NULL,
name   STRING  NOT NULL,
unit   STRING  NOT NULL,
sumrule[SMALLINT UNSIGNED] DEFAULT NULL,
created_at DATETIMEDEFAULT CURRENT_TIMESTAMP,
UNIQUE (
name,
unit,
sumrule
)
ON CONFLICT IGNORE
);





- Original Message - 
From: Dominique Devienne 
To: SQLite mailing list 
Sent: Thursday, October 31, 2019, 11:06:07
Subject: [sqlite] DELETE extremely slow

On Thu, Oct 31, 2019 at 10:57 AM Thomas Kurz  wrote:

> I'm using a database with 5 hierarchically strcutured tables using foreign
> keys. The largest table contains about 230'000 entries. My problem is that
> deleting in this database is extremely slow:

> pragma foreign_keys=on;
> pragma journal_mode=wal;
> .timer on
> delete from dataset;
> --> Run Time: real 197993.218 user 53015.593750 sys 54056.546875

> I experimentally imported the same data into a MariaDB database and tried
> the same operation there (without paying attention to creating any indexes,
> etc.). It takes only a few seconds there.

> Is there something I can check or do to improve deletion speed?


You're not describing the schema enough IMHO.
Is dataset the "top-most" table, containing the "parent" rows all other
tables references (directly or indirectly),
with all FKs having ON DELETE CASCADE?

If that's the case, without some kind of optimization in SQLite, when the
first parent row is deleted,
it triggers a cascade of deletes in "child" tables, looking for rows using
the parent row. So if your FKs
are not indexed for those column(s), that's a full table scan each time...
That's "depth first".

By analyzing the graph of FKs and their ON DELETE CASCADE state, and in the
specific case of
fully deleting the "main parent table", SQLite could decide switch to a
smarter "breadth first" delete,
but I suspect it's not a compelling enough use-case for Richard to invest
time on this.

Try indexing your FKs, and see what happens. --DD
___
sqlite-users mailin

Re: [sqlite] DELETE extremely slow

2019-10-31 Thread Dominique Devienne
On Thu, Oct 31, 2019 at 10:57 AM Thomas Kurz  wrote:

> I'm using a database with 5 hierarchically strcutured tables using foreign
> keys. The largest table contains about 230'000 entries. My problem is that
> deleting in this database is extremely slow:
>
> pragma foreign_keys=on;
> pragma journal_mode=wal;
> .timer on
> delete from dataset;
> --> Run Time: real 197993.218 user 53015.593750 sys 54056.546875
>
> I experimentally imported the same data into a MariaDB database and tried
> the same operation there (without paying attention to creating any indexes,
> etc.). It takes only a few seconds there.
>
> Is there something I can check or do to improve deletion speed?
>

You're not describing the schema enough IMHO.
Is dataset the "top-most" table, containing the "parent" rows all other
tables references (directly or indirectly),
with all FKs having ON DELETE CASCADE?

If that's the case, without some kind of optimization in SQLite, when the
first parent row is deleted,
it triggers a cascade of deletes in "child" tables, looking for rows using
the parent row. So if your FKs
are not indexed for those column(s), that's a full table scan each time...
That's "depth first".

By analyzing the graph of FKs and their ON DELETE CASCADE state, and in the
specific case of
fully deleting the "main parent table", SQLite could decide switch to a
smarter "breadth first" delete,
but I suspect it's not a compelling enough use-case for Richard to invest
time on this.

Try indexing your FKs, and see what happens. --DD
___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


[sqlite] DELETE extremely slow

2019-10-31 Thread Thomas Kurz
I'm using a database with 5 hierarchically strcutured tables using foreign 
keys. The largest table contains about 230'000 entries. My problem is that 
deleting in this database is extremely slow:

pragma foreign_keys=on;
pragma journal_mode=wal;
.timer on
delete from dataset;
--> Run Time: real 197993.218 user 53015.593750 sys 54056.546875

I experimentally imported the same data into a MariaDB database and tried the 
same operation there (without paying attention to creating any indexes, etc.). 
It takes only a few seconds there.

Is there something I can check or do to improve deletion speed?

Kind regards,
Thomas

___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users