-- ============================================================ -- SP-GiST Orbital Trie Benchmark (Phase 3) -- CelesTrak active catalog, ~14k satellites -- ============================================================ \timing on -- ============================================================ -- 1. Catalog distribution analysis -- ============================================================ SELECT CASE WHEN tle_perigee(tle) < 2000 THEN 'LEO (<2000km)' WHEN tle_perigee(tle) < 20000 THEN 'MEO (2000-20000km)' WHEN tle_perigee(tle) < 34000 THEN 'GEO-transfer' ELSE 'GEO/HEO (>34000km)' END AS regime, count(*) AS n, round(100.0 * count(*) / (SELECT count(*) FROM bench_catalog), 1) AS pct FROM bench_catalog GROUP BY 1 ORDER BY 2 DESC; -- ============================================================ -- 2. Create indexes -- ============================================================ \echo '--- CREATE SP-GiST INDEX ---' CREATE INDEX bench_spgist ON bench_catalog USING spgist (tle tle_spgist_ops); \echo '--- CREATE GiST INDEX ---' CREATE INDEX bench_gist ON bench_catalog USING gist (tle tle_ops); -- Index sizes SELECT indexname, pg_size_pretty(pg_relation_size(indexname::regclass)) AS size FROM pg_indexes WHERE tablename = 'bench_catalog' ORDER BY indexname; -- ============================================================ -- 3. Benchmark: 2h window, Eagle Idaho (43.7N) — RAAN active -- ============================================================ \echo '--- BENCHMARK 1: 2h window, Eagle Idaho, 10 deg min_el ---' -- 3a. Sequential scan (baseline) SET enable_indexscan = off; SET enable_bitmapscan = off; SELECT count(*) AS seqscan_candidates FROM bench_catalog WHERE tle &? ROW( observer('43.6977N 116.3535W 760m'), '2026-02-17 02:00:00+00'::timestamptz, '2026-02-17 04:00:00+00'::timestamptz, 10.0 )::observer_window; RESET enable_indexscan; RESET enable_bitmapscan; -- 3b. SP-GiST index scan SET enable_seqscan = off; SELECT count(*) AS spgist_candidates FROM bench_catalog WHERE tle &? ROW( observer('43.6977N 116.3535W 760m'), '2026-02-17 02:00:00+00'::timestamptz, '2026-02-17 04:00:00+00'::timestamptz, 10.0 )::observer_window; RESET enable_seqscan; -- ============================================================ -- 4. Benchmark: 24h window, Eagle Idaho — RAAN bypassed -- ============================================================ \echo '--- BENCHMARK 2: 24h window, Eagle Idaho, 10 deg min_el ---' SET enable_indexscan = off; SET enable_bitmapscan = off; SELECT count(*) AS seqscan_candidates FROM bench_catalog WHERE tle &? ROW( observer('43.6977N 116.3535W 760m'), '2026-02-17 00:00:00+00'::timestamptz, '2026-02-18 00:00:00+00'::timestamptz, 10.0 )::observer_window; RESET enable_indexscan; RESET enable_bitmapscan; SET enable_seqscan = off; SELECT count(*) AS spgist_candidates FROM bench_catalog WHERE tle &? ROW( observer('43.6977N 116.3535W 760m'), '2026-02-17 00:00:00+00'::timestamptz, '2026-02-18 00:00:00+00'::timestamptz, 10.0 )::observer_window; RESET enable_seqscan; -- ============================================================ -- 5. Benchmark: 2h window, Equatorial observer — all inc pass -- ============================================================ \echo '--- BENCHMARK 3: 2h window, Equator, 10 deg min_el ---' SET enable_indexscan = off; SET enable_bitmapscan = off; SELECT count(*) AS seqscan_candidates FROM bench_catalog WHERE tle &? ROW( observer('0.0N 0.0E 0m'), '2026-02-17 02:00:00+00'::timestamptz, '2026-02-17 04:00:00+00'::timestamptz, 10.0 )::observer_window; RESET enable_indexscan; RESET enable_bitmapscan; SET enable_seqscan = off; SELECT count(*) AS spgist_candidates FROM bench_catalog WHERE tle &? ROW( observer('0.0N 0.0E 0m'), '2026-02-17 02:00:00+00'::timestamptz, '2026-02-17 04:00:00+00'::timestamptz, 10.0 )::observer_window; RESET enable_seqscan; -- ============================================================ -- 6. Benchmark: 45 deg min_el (aggressive altitude filter) -- ============================================================ \echo '--- BENCHMARK 4: 2h window, Eagle Idaho, 45 deg min_el ---' SET enable_indexscan = off; SET enable_bitmapscan = off; SELECT count(*) AS seqscan_candidates FROM bench_catalog WHERE tle &? ROW( observer('43.6977N 116.3535W 760m'), '2026-02-17 02:00:00+00'::timestamptz, '2026-02-17 04:00:00+00'::timestamptz, 45.0 )::observer_window; RESET enable_indexscan; RESET enable_bitmapscan; SET enable_seqscan = off; SELECT count(*) AS spgist_candidates FROM bench_catalog WHERE tle &? ROW( observer('43.6977N 116.3535W 760m'), '2026-02-17 02:00:00+00'::timestamptz, '2026-02-17 04:00:00+00'::timestamptz, 45.0 )::observer_window; RESET enable_seqscan; -- ============================================================ -- 7. Consistency check: index and seqscan must agree -- ============================================================ \echo '--- CONSISTENCY CHECK ---' SET enable_indexscan = off; SET enable_bitmapscan = off; CREATE TEMPORARY TABLE seq_results AS SELECT norad_id FROM bench_catalog WHERE tle &? ROW( observer('43.6977N 116.3535W 760m'), '2026-02-17 02:00:00+00'::timestamptz, '2026-02-17 04:00:00+00'::timestamptz, 10.0 )::observer_window; RESET enable_indexscan; RESET enable_bitmapscan; SET enable_seqscan = off; CREATE TEMPORARY TABLE idx_results AS SELECT norad_id FROM bench_catalog WHERE tle &? ROW( observer('43.6977N 116.3535W 760m'), '2026-02-17 02:00:00+00'::timestamptz, '2026-02-17 04:00:00+00'::timestamptz, 10.0 )::observer_window; RESET enable_seqscan; -- These should both be 0 SELECT count(*) AS in_seq_not_idx FROM seq_results WHERE norad_id NOT IN (SELECT norad_id FROM idx_results); SELECT count(*) AS in_idx_not_seq FROM idx_results WHERE norad_id NOT IN (SELECT norad_id FROM seq_results); DROP TABLE seq_results, idx_results; -- ============================================================ -- 8. EXPLAIN ANALYZE for query plan details -- ============================================================ \echo '--- EXPLAIN ANALYZE: SP-GiST scan ---' SET enable_seqscan = off; EXPLAIN ANALYZE SELECT count(*) FROM bench_catalog WHERE tle &? ROW( observer('43.6977N 116.3535W 760m'), '2026-02-17 02:00:00+00'::timestamptz, '2026-02-17 04:00:00+00'::timestamptz, 10.0 )::observer_window; RESET enable_seqscan; \echo '--- EXPLAIN ANALYZE: Sequential scan ---' SET enable_indexscan = off; SET enable_bitmapscan = off; EXPLAIN ANALYZE SELECT count(*) FROM bench_catalog WHERE tle &? ROW( observer('43.6977N 116.3535W 760m'), '2026-02-17 02:00:00+00'::timestamptz, '2026-02-17 04:00:00+00'::timestamptz, 10.0 )::observer_window; RESET enable_indexscan; RESET enable_bitmapscan; -- ============================================================ -- Cleanup -- ============================================================ DROP TABLE bench_catalog; \timing off