The AS map previously exploded ~4.4M base_attrs AS_PATH rows live, three times per load (one per panel), ~1.8s each — slow enough that navigating away cancelled the queries mid-flight. Add mv_as_adjacency: undirected consecutive-AS pairs with occurrence counts over the full RIB (17k rows), refreshed hourly by pg_cron via REFRESH ... CONCURRENTLY. The dashboard panels now read the view in ~1ms. Min-occurrence options rescaled for full-RIB counts (2000/5000/10000/50000, default 2000 -> ~63-node graph). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
27 lines
1.3 KiB
SQL
27 lines
1.3 KiB
SQL
-- OBMP analytics materialized views
|
|
--
|
|
-- Applied to the live database and version-controlled here for reproducibility.
|
|
-- Safe to run against an empty database at init time: the view is created empty
|
|
-- and the pg_cron job below populates/refreshes it hourly.
|
|
|
|
-- AS adjacency: every undirected pair of consecutive ASes in an observed AS_PATH,
|
|
-- with an occurrence count. Backs the AS Relationship Map dashboard so its panels
|
|
-- read a 17k-row view instead of exploding ~4.4M base_attrs rows live.
|
|
CREATE MATERIALIZED VIEW IF NOT EXISTS mv_as_adjacency AS
|
|
SELECT LEAST(a.asn, b.asn) AS asn_a,
|
|
GREATEST(a.asn, b.asn) AS asn_b,
|
|
COUNT(*) AS occ
|
|
FROM base_attrs ba
|
|
CROSS JOIN LATERAL unnest(ba.as_path) WITH ORDINALITY a(asn, ord)
|
|
JOIN LATERAL unnest(ba.as_path) WITH ORDINALITY b(asn, ord) ON b.ord = a.ord + 1
|
|
WHERE ba.as_path_count >= 2 AND a.asn <> b.asn
|
|
GROUP BY 1, 2;
|
|
|
|
-- Unique index required for REFRESH ... CONCURRENTLY (no read lock during refresh).
|
|
CREATE UNIQUE INDEX IF NOT EXISTS mv_as_adjacency_pair_idx ON mv_as_adjacency (asn_a, asn_b);
|
|
CREATE INDEX IF NOT EXISTS mv_as_adjacency_occ_idx ON mv_as_adjacency (occ DESC);
|
|
|
|
-- Refresh hourly at minute 23.
|
|
SELECT cron.schedule('refresh-mv-as-adjacency', '23 * * * *',
|
|
'REFRESH MATERIALIZED VIEW CONCURRENTLY mv_as_adjacency');
|