mirror of
https://github.com/zotero/zotero.git
synced 2026-09-29 01:41:24 +00:00
When an item is erased (removed from the trash or cleaned up from a feed), we set a flag to purge values in `itemDataValues` on the next startup, with this query: DELETE FROM itemDataValues WHERE valueID NOT IN (SELECT valueID FROM itemData); For some people, that query was incredibly slow and would result in Zotero intermittently hanging on "Loading items…" for a long time at startup. It's possible this is mostly limited to people who subscribe to high-volume feeds and have a lot of item churn. One affected person had >900K values in `itemDataValues` despite having only 20K items. It turns out the slow query is due to the foreign-key constraint on `itemData(valueID)` that references`itemDataValues(valueID)`. SQLite is checking every row being deleted from `itemDataValues` against `itemData`, even though the query is specifically removing rows that don't exist in `itemData`! For the 900K-value DB, disabling foreign-key checks causes the `DELETE` query to take 25 seconds instead of...some much longer time that I didn't wait for. We already had an `executeTransaction()` flag, `disableForeignKeys`, to temporarily disable foreign-key checks, but it didn't do so in a way that was safe for post-initialization usage -- a write query outside of a transaction could've run between the transaction commit and foreign-key checks being re-enabled. This commit changes it to properly block all other queries unless they include an `ignoreDBLock` option, meaning that queries within the function passed to the transaction need to include that option. (And since that's not realistic for the couple other uses of `disableForeignKeys` -- one for a test and one in code that almost certainly hasn't been run by anyone in 15 years -- those now just run `PRAGMA foreign_keys=OFF|ON` explicitly, leaving this as the only current use.) |
||
|---|---|---|
| .. | ||
| content | ||
| locale | ||
| skin/default/zotero | ||