Files
chatmail-core/src
link2xt 4dd0ba2c72 fix: move sorting outside of SQL query in store_seen_flags_on_imap
With `ORDER BY` statement SQLite searches
the `imap` table by `transport_id` and for each found row
scans the whole `imap_markseen` table.
Number of `imap` entries for each `transport_id`
is usually large as we need to know
which UIDs to delete on IMAP server
when deleting a message.

```
sqlite> EXPLAIN QUERY PLAN
SELECT imap.id, uid, folder FROM imap, imap_markseen
WHERE imap.id = imap_markseen.id
AND imap.transport_id=?
AND target = folder
ORDER BY folder, uid;
QUERY PLAN
|--SEARCH imap USING INDEX sqlite_autoindex_imap_1 (transport_id=?)
`--SCAN imap_markseen
```

Without `ORDER BY` statement SQLite scans `imap_markseen`
table which is expected to be small,
and then searches `imap` table by `rowid` for each found result.

```
sqlite> EXPLAIN QUERY PLAN
SELECT imap.id, uid, folder FROM imap, imap_markseen
WHERE imap.id = imap_markseen.id
AND imap.transport_id=?
AND target = folder;
QUERY PLAN
|--SCAN imap_markseen
`--SEARCH imap USING INTEGER PRIMARY KEY (rowid=?)
```

Query planning was tested with SQLite 3.52.0.
It is possible to explictly make
query planner move sorting to the last step
with `ORDER +folder, +uid`, but this is not recommended
in SQLite documentation
(see <https://www.sqlite.org/optoverview.html#uplus>).

It is also possible to add indexes,
but indexes use space,
adding them requires an SQL migration,
and each index needs to be updated so it will slow down writes.
2026-03-26 16:24:11 +00:00
..
2026-03-25 19:53:10 +00:00
2025-11-16 14:48:50 +00:00
2026-03-25 20:31:53 +00:00
2026-03-25 19:53:10 +00:00
2026-02-03 18:31:55 +00:00
2025-10-26 07:08:54 +00:00
2026-03-25 19:53:10 +00:00
2026-03-17 20:08:38 +00:00
2026-02-23 15:58:06 +00:00
2025-11-08 03:26:23 +00:00
2026-03-25 20:31:53 +00:00
2026-03-25 20:31:53 +00:00
2026-03-25 19:53:10 +00:00
2026-03-25 19:53:10 +00:00
2026-03-25 20:31:53 +00:00
2026-03-25 19:53:10 +00:00
2025-06-26 14:07:39 +00:00