Skip to content

docs(sql): 5.2 SQL engine performance guidance#588

Open
kriszyp wants to merge 5 commits into
mainfrom
kris/sql-52-engine-guidance
Open

docs(sql): 5.2 SQL engine performance guidance#588
kriszyp wants to merge 5 commits into
mainfrom
kris/sql-52-engine-guidance

Conversation

@kriszyp

@kriszyp kriszyp commented Jul 15, 2026

Copy link
Copy Markdown
Member

Adds guidance to the SQL operations-api reference for the new Resource-API SQL engine landing in 5.2 (harper #1285 — New SQL engine on the Resource API), per Kris's request to document which SQL is well supported / runs efficiently and what to avoid.

Changes to reference/operations-api/sql.md

  • Replaced the blanket "SQL is not recommended for production" warning with an accurate 5.2 note: the new engine serves index-plannable queries as streaming, bounded-memory operations and transparently falls back to the legacy path for anything it can't plan. REST is still steered as the choice for the hottest production read paths.
  • New ## Query Performance section:
    • Index-served (efficient): PK lookups, equality/IN on indexed attributes, range/BETWEEN, prefix LIKE 'x%', index-order ORDER BY with LIMIT/OFFSET pushdown, GROUP BY on an indexed attribute, INNER/LEFT JOIN on an indexed inner key, projection pushdown.
    • Full-scan fallback (avoid on large tables): un-indexed predicates, cross-attribute OR, suffix/substring LIKE, !=/NOT negations, un-driven ORDER BY, SEARCH_JSON; plus a note that RIGHT/FULL JOIN, no-WHERE UPDATE/DELETE, and COUNT(DISTINCT) run on the legacy engine.
    • The fallback contract: auto default, results never change (only the performance profile), and the sql-engine v2 fallback: log signal.
    • Practical guidance: index what you filter/sort/join on, prefer prefix LIKE, constrain before sort/group/join/SEARCH_JSON, use REST for hot paths.

Accuracy notes

  • Guidance is grounded in the engine's optimizer rules (predicate normalization for LIKE/BETWEEN, sort-from-index, validate-scannable) and the phase-5 cutover parity work in #1285.
  • Reconciled against the existing Features Matrix: UNION, sub-SELECT, and INSERT … SELECT are unsupported by both engines, so they are called out as "not supported" rather than "slow fallback."
  • Verified the RIGHT/FULL JOIN fallback claim against source: normalizer.ts throws EngineUnsupportedError for both, and the router catches exactly that under auto to fall back to legacy (which supports them).

Note: #1285 is still open and targeted at 5.2; the "As of Harper 5.2" framing lines up with that release. If the merge/version slips, the version reference should move with it.

🤖 Generated with Claude Code

Document the new Resource-API SQL engine landing in 5.2 (harper #1285):
which queries run index-served/streaming vs. which fall back to the
legacy full-scan path, and the auto-fallback contract. Replace the blanket
"SQL not recommended" warning with accurate, nuanced guidance.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kriszyp
kriszyp requested a review from a team as a code owner July 15, 2026 19:40

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the SQL documentation for Harper 5.2, introducing the new SQL engine built on indexed storage and the Resource API. It replaces the previous warning against SQL use in production with an informative block and adds a comprehensive 'Query Performance' section detailing index-served queries, full-scan fallbacks, and practical optimization guidance. There are no review comments, so no further feedback is provided.

@github-actions
github-actions Bot temporarily deployed to pr-588 July 15, 2026 19:43 Inactive
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-588

This preview will update automatically when you push new commits.

@kriszyp
kriszyp removed the request for review from a team July 15, 2026 20:06
…full scan

Table.search executes a top-level OR as a union of per-condition index
searches (resources/search.ts), and the new engine pushes an OR group down
when every branch is index-driving (whereToConditions conditionUsesIndex).
So `a = 1 OR b = 2` with both attributes indexed is index-served; only an
OR with an un-indexed / non-index-comparator branch falls back to a scan.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kriszyp

kriszyp commented Jul 15, 2026

Copy link
Copy Markdown
Member Author

Follow-up commit (14d4523) corrects the OR guidance. An earlier draft said WHERE a = 1 OR b = 2 always forces a full scan — that's wrong. Table.search executes a top-level OR as a union of per-condition index searches (resources/search.ts), and the new engine pushes the disjunction down when every branch is index-driving (conditionUsesIndex in whereToConditions.ts). So an all-indexed OR is index-served; only an OR with an un-indexed (or non-index-comparator, e.g. %x% LIKE) branch falls back to a scan. Doc now reflects that in both the index-served and fallback lists.

@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-588

This preview will update automatically when you push new commits.

@github-actions
github-actions Bot temporarily deployed to pr-588 July 15, 2026 20:16 Inactive
Comment thread reference/operations-api/sql.md Outdated
Comment thread reference/operations-api/sql.md
Comment thread reference/operations-api/sql.md Outdated
Comment thread reference/operations-api/sql.md Outdated
Adds a 'Behavior changes from the legacy engine' subsection covering the
standard-SQL corrections the new engine applies to queries it plans (empty-set
aggregates -> NULL, string MIN/MAX, NULL!=NULL join keys, explicit-null
expression results), and scopes the fallback-contract 'results don't change'
promise to genuine fallbacks. Adds TOTAL to the reserved-word list and notes
that reserved words used as AS aliases must be quoted (e.g. AS `total`).

Sourced from the sql-engine-v2 QA differential wave (findings D-217, F-143).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions
github-actions Bot temporarily deployed to pr-588 July 15, 2026 21:32 Inactive
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-588

This preview will update automatically when you push new commits.

…equirement; OFFSET behavior change

QA verification against the engine (sql-engine-v2 @ 8a46e0302) found three
inaccuracies:
- The fallback log line is 'SQL engine v2 fallback:' (router.ts), not
  'sql-engine v2 fallback:' — the documented grep string matched nothing.
- ORDER BY / GROUP BY on an indexed attribute run on the legacy path unless
  an index-driving WHERE condition is present (validateScannable requires a
  scan driver) — state the requirement instead of promising them
  unconditionally.
- Behavior changes: OFFSET past the end of a result now correctly returns
  no rows (legacy could still return rows).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-588

This preview will update automatically when you push new commits.

@github-actions
github-actions Bot temporarily deployed to pr-588 July 15, 2026 22:50 Inactive
@kriszyp
kriszyp requested a review from cb1kenobi July 17, 2026 16:49
Comment thread reference/operations-api/sql.md Outdated
…ual filters, over-indexing, observability, callout

- ORDER BY bullet: correct the WHERE-driver requirement to note the
  primary-key exception (validateScannable/sortDrivesIndex only checks
  isPrimaryKey; a no-WHERE ORDER BY on the PK is index-served, only a
  secondary indexed attribute falls back) — cb1kenobi
- Un-indexed-filter bullet: clarify that ANDed with an indexed predicate
  it's a cheap residual filter and the query stays index-served; only a
  standalone or OR-joined un-indexed filter forces a scan — kylebernhardy
- Practical guidance: note the storage/write-cost tradeoff of indexing
  every attribute — kylebernhardy
- Intro info box: point to the `SQL engine v2 fallback: ...` log line as
  the observability signal for query planning — kylebernhardy
- Query Performance intro: add a callout emphasizing that fallback means
  reading every row in the table, not just "slower" — kylebernhardy

Verified against harper sqlEngine/optimizer/{validateScannable,whereToConditions}.ts
and unitTests/sqlEngine/pipeline.test.js (D-219 PK exception tests).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@kriszyp

kriszyp commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

Addressed all 5 open threads in 82e074c:

  • cb1kenobi — confirmed and fixed the ORDER BY PK exception (sortDrivesIndex/validateScannable only checks isPrimaryKey; verified against unitTests/sqlEngine/pipeline.test.js's D-219 tests).
  • kylebernhardy (observability) — the only signal today is the SQL engine v2 fallback: ... log line (sqlEngine/router.ts); no EXPLAIN or response metadata exists yet. Pointed to it from the intro.
  • kylebernhardy (AND with an indexed filter) — confirmed via whereToConditions.ts: an un-indexed conjunct ANDed with an indexed one is pushed as a residual filter post-scan, so it stays index-served overall (same treatment as suffix LIKE). Clarified the bullet.
  • kylebernhardy (full-scan callout) — added a :::caution admonition.
  • kylebernhardy (over-indexing) — added a line on storage/write-cost tradeoffs.

🤖 Signed, Claude Sonnet 5

@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-588

This preview will update automatically when you push new commits.

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.

3 participants