Add 30k Space-Track catalog and benchmark results

Space-Track USSPACECOM catalog: 29,784 objects from full GP query.
Benchmark shows SP-GiST index reaches parity with seqscan at 30k:
  - Delta: +1.6ms (14k) -> +0.9ms (20k) -> +0.0ms (30k)
  - Planner voluntarily chooses Index Only Scan at this scale
  - Zero heap fetches (all data served from index pages)
  - 75.9% candidate pruning on 2h/10deg query

Archive includes TLEs from Space-Track, TLE API, and SatNOGS.
This commit is contained in:
Ryan Malloy 2026-02-17 22:22:58 -07:00
parent 5e5588fddb
commit 13d49c1072
4 changed files with 149821 additions and 0 deletions

View File

@ -0,0 +1,115 @@
pg_orrery v0.7.0 SP-GiST Benchmark — 30k Space-Track Catalog
=============================================================
Date: 2026-02-17
Catalog: Space-Track USSPACECOM full catalog (29,784 objects)
Host: Linux 6.16.5-arch1-1, PostgreSQL 17
Branch: phase/spgist-orbital-trie
Catalog Composition:
LEO (<128 min): 25,641 (86.1%)
MEO (128-720 min): 1,801 ( 6.0%)
GEO/HEO (720-1500 min): 2,253 ( 7.6%)
Super-GEO (>1500 min): 89 ( 0.3%)
Index Build:
SP-GiST: 46.7 ms, 4,816 kB
GiST: 65.8 ms, 5,856 kB
Table: 4,760 kB
==============================================================
TIMING RESULTS (best of 3 runs, ms)
==============================================================
Query Pattern | Seqscan | SP-GiST | Delta
-----------------------------|---------|---------|-------
2h window, Eagle ID, 10 deg | 5.19 | 5.22 | +0.03
6h window, Eagle ID, 10 deg | 5.34 | 6.34 | +1.00
24h window, Eagle ID, 10 deg | 5.42 | 6.68 | +1.26
2h window, Eagle ID, 30 deg | 5.54 | 5.64 | +0.10
2h window, equatorial, 10deg | 5.26 | 5.59 | +0.33
==============================================================
PRUNING RESULTS
==============================================================
Query Pattern | Candidates | % Pass | % Pruned
-----------------------------|------------|--------|---------
2h window, Eagle ID, 10 deg | 7,188 | 24.1% | 75.9%
6h window, Eagle ID, 10 deg | 12,373 | 41.5% | 58.5%
24h window, Eagle ID, 10 deg | 26,971 | 90.6% | 9.4%
2h window, Eagle ID, 30 deg | 5,232 | 17.6% | 82.4%
2h window, equatorial, 10deg | 4,670 | 15.7% | 84.3%
==============================================================
BUFFER I/O COMPARISON (2h Eagle 10deg)
==============================================================
Method | Pages Read | Heap Fetches | Scan Type
------------|------------|--------------|------------------
Seqscan | 595 | n/a | Seq Scan
SP-GiST | 2,396 | 0 | Index Only Scan
SP-GiST reads 4.0x more pages than seqscan (2,396 vs 595).
But uses Index Only Scan with zero heap fetches.
==============================================================
CONSISTENCY CHECK
==============================================================
False negatives: 0 (index never misses a seqscan result)
False positives: 0 (index never returns extra results)
Seqscan count: 7,188
SP-GiST count: 7,188
==============================================================
SCALING TREND (2h Eagle 10deg, best-of-3)
==============================================================
Catalog Size | Seqscan | SP-GiST | Delta | SP-GiST Pages | Seq Pages
-------------|---------|---------|--------|---------------|----------
14,376 | 4.5 ms | 6.1 ms | +1.6ms | 888 | 291
20,597 | 3.8 ms | 4.7 ms | +0.9ms | (IOOS) | (est)
29,784 | 5.2 ms | 5.2 ms | +0.0ms | 2,396 | 595
The delta is converging toward zero. At 30k the SP-GiST index is
essentially tied with seqscan on the 2h/10deg query. For queries
with fewer survivors (30deg elevation, equatorial observer), the
index is within 0.1-0.3ms.
==============================================================
PLANNER BEHAVIOR
==============================================================
PostgreSQL's query planner CHOOSES the SP-GiST index by default
at 30k (without any enable_seqscan=off forcing). The planner's
cost model prefers the Index Only Scan.
EXPLAIN output (default settings):
Index Only Scan using bench_spgist on bench_catalog
Index Cond: (tle &? ...)
Heap Fetches: 0
Buffers: shared hit=2396
Execution Time: 7.246 ms (with planning)
==============================================================
NOTES
==============================================================
1. At 30k objects, the planner voluntarily chooses SP-GiST over
seqscan. This is the crossover point where the index becomes
the planner's preferred strategy.
2. The Index Only Scan with zero heap fetches means the index
contains all information needed — no table access required.
3. The 75.9% pruning rate on the 2h window means only 7,188 of
29,784 satellites need SGP4 propagation. This avoids ~22,596
unnecessary SGP4 calls in the predict_passes() pipeline.
4. The equatorial observer (84.3% pruned) and high-elevation
(82.4% pruned) queries show the strongest filtering because
the altitude and RAAN filters are most aggressive there.
5. The 24h window only prunes 9.4% because the RAAN filter
self-disables for full Earth rotations, leaving only the
altitude and inclination filters active.

59577
bench/load_spacetrack.sql Normal file

File diff suppressed because it is too large Load Diff

90129
bench/spacetrack_full.tle Normal file

File diff suppressed because it is too large Load Diff

BIN
bench/tle_archives.tar.gz Normal file

Binary file not shown.