Skip to content

Every sec ask full-scans and temp-B-tree-sorts filing_document: no index on filing_date, plus an unconditional COUNT nothing renders #366

Description

@sroussey

6ab497fa fixed the right thing — the limit now bounds work rather than embeddings (#351) — but
the selection it introduced is O(N) in converted filings, and sec ask runs it twice on
every question.

ask.ts:112-116 builds the index implicitly unless --no-index, so each question runs
selectDocumentsToIndex and countAlreadyIndexed. Both scan filing_document, and the first
also sorts it:

src/task/kb/selectDocumentsToIndex.ts:127-136

SELECT d.* FROM `filing_document` d
LEFT JOIN `kb_document` k ON k.`doc_id` = d.`accession_number` || ':' || d.`doc_file`
WHERE d.`section_count` > 0 AND k.`doc_id` IS NULL
ORDER BY d.`filing_date` DESC, d.`accession_number` DESC
LIMIT ?

filing_document carries exactly two indexes (storageRegistry.ts:239):
["form","converter_version","is_primary"] and ["converted_at"]. Neither covers
filing_date
, so the LIMIT cannot terminate the scan.

Measured

Faithful copy of the real DDL and both real indexes, 300,000 rows, 99% already in kb_document
(the steady state ask runs in), LIMIT 26 (DEFAULT_ASK_INDEX_LIMIT + 1):

QP: SCAN d
QP: SEARCH k USING COVERING INDEX sqlite_autoindex_kb_document_1 (doc_id=?) LEFT-JOIN
QP: USE TEMP B-TREE FOR ORDER BY
selectDocumentsToIndex LIMIT 26, no filing_date index: 415 ms / 416 ms

CREATE INDEX fd_filing_date ON filing_document (filing_date DESC, accession_number DESC);

QP: SCAN d USING INDEX fd_filing_date
QP: SEARCH k USING COVERING INDEX sqlite_autoindex_kb_document_1 (doc_id=?) LEFT-JOIN
selectDocumentsToIndex LIMIT 26, WITH filing_date index:  21 ms / 12 ms

20–35× on an in-memory database, and the indexed plan is O(limit) rather than O(N) — the
gap widens with the corpus and widens again on disk with a cold page cache. This sits on top of
the chunk-scan cost in the sibling issue, on the same question.

The second scan

countAlreadyIndexed (:152-189) is a full filing_document ⋈ kb_document COUNT, run
unconditionally whenever force !== true, to populate skipped. The ask renderer never prints
skipped; only sec index does (ask.ts:71). So half the per-question cost is computed for a
field the caller discards.

Fix

  1. Add ["filing_date", "accession_number"] to filing_document's indexes in
    src/config/storageRegistry.ts — one entry, and db setup / addMissingColumns already loop
    the registry.
  2. Skip countAlreadyIndexed when the caller will not render it (an option on the task input, or
    compute it lazily), and consider whether ask's implicit index needs a selection at all when
    kb_chunk is non-empty and the scope is unchanged.

Smaller, same file

  • countAlreadyIndexed omits the section_count > 0 clause the selection applies, so skipped
    can count documents the selection would never return.
  • selectDocumentsToIndex's JSDoc says "newest first"; the repository arm selectByScan
    (:205-222) returns repository order, so under --limit N the two paths select different
    documents.

Found during the 2026-09-14 review. Snapshot: workglow-dev/prdanalysis/grades/2026-09-14/sec-detailed.md §4.6.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions