New docs: - guides/pass-prediction.mdx: two-stage workflow (SP-GiST filter then SGP4 propagation), query window comparison tabs, GiST/SP-GiST coexistence example - reference/operators-gist.mdx: &? operator signature and description, observer_window type reference, SP-GiST operator class docs with eccentricity/HEO limitation aside Benchmarks on 14,376 CelesTrak active satellites: - SP-GiST index: 2,344 kB, builds in 19 ms - GiST index: 2,904 kB, builds in 45 ms - Consistency: 0 false negatives, 0 false positives - At 14k catalog size, seqscan (~6 ms) still beats index scan (~8 ms) due to low page count; cross-over expected at ~100k objects
235 lines
6.9 KiB
SQL
235 lines
6.9 KiB
SQL
-- ============================================================
|
|
-- 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
|