docs: add query engine optimizations section with measured throughput

ober

be708ae6f358461acdc8c1cd81c7fea90e8c1fd0

diff --git a/docs/jerboa-db.md b/docs/jerboa-db.md
index 4eb7961..cc15081 100644
--- a/docs/jerboa-db.md
+++ b/docs/jerboa-db.md
@@ -1536,6 +1536,31 @@ project and a multi-year one.
 | Content-addressed value store | Done | FNV-1a keyed in-memory hashtable; `value-store-put!` deduplicates equal values |
 | Transaction log durability | Done | `sync` foreign-procedure called after each segment write to guarantee fsync on flush |
 
+### Query Engine Performance Optimizations (implemented)
+
+| Optimization | Description | Benefit |
+|---|---|---|
+| AVET for all scalar attrs | Every non-ref, non-tuple attribute populates the AVET index | Exact-match and range queries use index instead of full AEVT scan |
+| Binding hashtable | Binding env is an `eq?` hashtable instead of alist | O(1) variable lookup vs O(n) for deep join pipelines |
+| Streaming flatmap | `evaluate-where-clauses` uses inline flatmap instead of `(apply append (map …))` | Avoids intermediate list-of-lists allocation |
+| Early termination | Clause evaluation stops immediately when no bindings survive | Avoids evaluating remaining clauses on empty result set |
+| Count short-circuit | `(count ?x)` with no grouping vars skips per-row extraction | Direct `(length bindings-list)` — O(1) vs O(n) |
+| Range predicate pushdown | `(?e attr ?v) [(cmp ?v const)]` fused into single AVET range scan | Scans only the qualifying value range; fires only when entity is unbound |
+| Schema lookup cache | Per-transaction `symbol-hash` hashtable wrapping `schema-lookup-by-ident` | Eliminates repeated global hashtable lookups per datom during write |
+| Retraction fast-path | `resolve-current-datoms` skips hashtable when no retractions present | Common case (append-only DB) avoids O(n) hashtable build |
+
+**Measured throughput (in-memory, 5,000 entities, Chez Scheme native):**
+
+| Query | Rate | Notes |
+|---|---|---|
+| Exact-match (`(?e attr const)`) | ~60K ops/sec | AVET point lookup, ~80 results |
+| Range predicate (`[(> ?v 50)]`) | ~1.5K ops/sec | AVET range scan, ~2300 results |
+| Three-attr join with range filter | ~400 ops/sec | EAVT point lookups per entity after anchor |
+| Count aggregate (full scan) | ~1.4K ops/sec | Count short-circuit, no per-row extraction |
+| Pull wildcard | ~1M ops/sec | Single EAVT range, cached tree traversal |
+| Individual writes (1 entity/tx) | ~90K ops/sec | Includes EAVT + AEVT + AVET + VAET insertion |
+| Batch writes (batch=500) | ~115K ops/sec | Schema cache amortizes lookup across datoms |
+
 ---
 
 ## Risks and Mitigations