Repository navigation
Sort and page lists in SQL - #1110
Conversation
|
CC @dsblank |
When a list is sorted only by change time, privacy or Gramps ID, the handles of the requested page are now read with one SQL query on the secondary columns, and the total with a COUNT, instead of reading the raw data of all objects. For users without ViewPrivate, RestrictedDb adds its visibility condition; citations and notes, whose visibility isn't decided by the private column alone, are paged after filtering. Sorting by change time is the frontend's default for all lists.
e0d7f0f to
469108a
Compare
dsblank
left a comment
There was a problem hiding this comment.
I tested this against a SharedPostgreSQL tree with about 100k people (PostgreSQL 16; 1.1k–331k rows per class). For 7 classes and the sorts -change, gramps_id, -gramps_id and -private,change, as both owner and guest, the SQL order was identical to the sort_handles_by_raw_data order. Pages at offsets 0, 20, near the end and past the end matched too, with the same totals. Guest citations and notes, which are filtered before paging, matched as well. The Gramps ID sorts were only compared with the en locale (en_US libc collation). Sorting a whole class took 0.07–0.35 s in SQL, against 0.9–3.9 s for the raw-data path. The new tests plus tests/test_access.py pass locally (154 passed).
One problem is confirmed (inline below), plus two smaller points. On tests: nothing covers a collation that can't be created or the list endpoint itself (pages and X-Total-Count through base.py), and test_uses_sql checks only Person with -change.
On PostgreSQL, creating the collation for the UI locale fails if the database server has no OS locale for it. Lists sorted by Gramps ID then failed, while they used to be sorted in Python. Now they are sorted in Python again, and the failure is logged once per collation. Also: - don't sort in SQL on SharedPostgreSQL without a tree ID - don't try SQL a second time after page_handles_in_sql declined - test pages and X-Total-Count through the list endpoints
Follow-up to #1107: list endpoints sort and page in SQL when the sort keys are secondary columns, instead of reading the raw data of the whole table.
Implementation
change,privateandgramps_id, in any combination and direction. Everything else still uses the existing Python paths.handle, withCOLLATE "C"on PostgreSQL, so the order equals that ofsort_handles_by_raw_data.gramps_iduses the locale's collation, as created bycheck_collation()(moved fromobject_query.pytodb_backend.resolve_collation).LIMIT/OFFSETand aCOUNT(*)forX-Total-Count, both scoped to the tree onSharedPostgreSQL.RestrictedDb.get_sorted_handlesadds its policy's condition (private = 0) to the query. Citations and notes, whose visibility also depends on other records, are sorted in SQL but paged after filtering in Python.sortare sorted by Gramps ID since Replace the private proxy with RestrictedDb #1107, so they now take the SQL path too.Tests
tests/test_sort_sql.pychecks for every class, sort key combination and direction that the SQL order equals the raw-data order, that pages match the slices of the full order, and that the SQL path is actually used. The equivalence was also checked by hand on PostgreSQL.Performance
One page of a list on a synthetic tree with 100k people (~485k objects), before → after:
sort=-change(frontend default)Across the same four setups, events with
sort=-changewent from about 0.9–1.4 s to 180–200 ms, and lists sorted by Gramps ID from about 0.8–1.4 s to 190–380 ms.