On 10/01/2015 10:32 PM, Andrew Cunningham wrote:
> I have noticed that when FOREIGN KEY is in DEFERRED mode and a FOREIGN KEY
> violation occurs, SQLite will continue to run, but performance slows down
> by about 1000x. Breaking into the code shows that it seems to be
> continually re-reading the database. When I finally get to COMMIT , an
> exception is thrown, but this can take hours , literally as I have a single
> global transactions.
>
> Of course the solution is to debug the problem by setting the mode to
> IMMEDIATE, detecting the issue at the source, then returning to DEFERRED.
>
> But the '1000x slowdown' behavior is an interesting quirk I don't really
> understand.
>


SQLite uses a counter to enforce deferred foreign keys. Each time an 
operation violates a constraint it increments that counter.

If the counter is greater than 0, then for every operation that might 
potentially correct the violation (which means virtually every operation 
on any table that is the parent or child in an FK constraint) it does 
extra seeks to see if it really does. i.e. each time you insert into the 
parent table, it seeks within the child table to see if the insert fixes 
a foreign key violation. And if it does, the counter is decremented.

So we know there is overhead, but I'm quite surprised that it is 1000x 
slower.

How large is the database? So large that these extra seeks could be 
performing real IO (i.e. having to go all the way to the disk for every 
seek, not just finding the data in the OS cache)?

Thanks,
Dan.


Reply via email to