Skip to content

Serve sorted searches from an index, and page past an id of 0 (fkie-cad/mcritweb#59) - #162

Open
r0ny123 wants to merge 1 commit into
danielplohmann:mainfrom
r0ny123:fix/59-sorted-search-indexes
Open

Serve sorted searches from an index, and page past an id of 0 (fkie-cad/mcritweb#59)#162
r0ny123 wants to merge 1 commit into
danielplohmann:mainfrom
r0ny123:fix/59-sorted-search-indexes

Conversation

@r0ny123

@r0ny123 r0ny123 commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Closes fkie-cad/mcritweb#59 (labelled mcrit): searches sorted by anything but the id had no index to be served from.

What changed

  • _ensureIndexAndUnknownFamily creates a compound (field, id) index for every field the search results can be sorted by in MCRITweb: families family_name, num_samples, num_library_samples, num_functions; samples family_id, family, filename, version, bitness, sha256, statistics.num_functions; functions family_id, sample_id, function_name, offset, num_instructions, num_blocks. As with the v1.6.2 indexes, the first start after upgrading builds them.
  • The search cursor's tie-break now follows the direction of the sort field (_get_sort_data). The order stays total and deterministic, and one index serves the descending order by being walked backwards; with (field asc, id asc) and a (field desc, id asc) sort no single index could.
  • Found on the way, fixed here because the paging test needed it: paging stopped early whenever a page ended on id 0. The forward cursor was built behind if last_element_key:, which is False for function 0, sample 0 and the unknown family 0. It is is not None now. The details are in the commit message and the test.

Measured

explain() on a real database, filter function_name regex, sort num_blocks/offset/function_name (functions), family (samples), num_samples (families), both directions:

before after
winning plan SORT → FETCH → IXSCAN (blocking in-memory sort of every filtered document) LIMIT → FETCH → IXSCAN (index order, stops at the limit)

A mongo-backed test asserts the indexes exist and that the plan for a sorted search has no SORT stage; another pages a listing to the end in both directions on the memory backend.

ruff, ty and the full suite pass.

A search sorted by anything but the id had no index to be served from: the
planner filtered on the search field and then sorted every matching document
in memory (a blocking SORT stage on every such query, on functions the whole
filtered set), which is the ~10x reported in fkie-cad/mcritweb#59. Each field
the results can be sorted by now carries a compound (field, id) index; the
tie-break follows the direction of the sort field, so the same index is
walked backwards for the descending order instead of needing a second one.
The plan for every sortable field is LIMIT -> FETCH -> IXSCAN afterwards,
which a mongo-backed test asserts. As with the v1.6.2 indexes, the first
start after upgrading builds them.

Paging through a sorted listing also stopped early whenever a page ended on
id 0: the forward cursor was built behind `if last_element_key:`, which is
False for function 0, sample 0 and the unknown family 0. It is `is not
None` now, with a test that pages a listing to the end in both directions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

add compound index for search (when sorted by s.th. different then id)

1 participant