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.
116 lines
4.6 KiB
Plaintext
116 lines
4.6 KiB
Plaintext
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.
|