Files
rf4-spotter/deploy/query-plan-gate.sql
T

118 lines
4.3 KiB
SQL

\set ON_ERROR_STOP on
\timing off
-- Session-local alpha-sized fixture. No production row is inserted or changed.
SET search_path = pg_temp, public;
SET jit = off;
SET work_mem = '16MB';
CREATE TEMP TABLE fish (LIKE public.fish INCLUDING ALL);
CREATE TEMP TABLE waterbody (LIKE public.waterbody INCLUDING ALL);
CREATE TEMP TABLE bait (LIKE public.bait INCLUDING ALL);
CREATE TEMP TABLE spot (LIKE public.spot INCLUDING ALL);
CREATE TEMP TABLE catch_report (LIKE public.catch_report INCLUDING ALL);
INSERT INTO fish (id, slug, name_ru, trophy_weight_g)
SELECT md5('fish-' || g)::uuid, 'fish-' || g, 'Рыба ' || g, 5000 + g * 20
FROM generate_series(1, 252) AS g;
INSERT INTO waterbody (id, slug, name_ru, unlock_level)
SELECT md5('water-' || g)::uuid, 'water-' || g, 'Водоём ' || g, g
FROM generate_series(1, 19) AS g;
INSERT INTO bait (id, name, normalized_name, kind)
SELECT md5('bait-' || g)::uuid, 'Приманка ' || g, 'приманка-' || g,
CASE WHEN g % 3 = 0 THEN 'bait'::baitkind ELSE 'lure'::baitkind END
FROM generate_series(1, 500) AS g;
INSERT INTO spot (id, waterbody_id, x, y, description)
SELECT md5('spot-' || g)::uuid,
md5('water-' || ((g - 1) % 19 + 1))::uuid,
(g * 37) % 1000, (g * 61) % 1000, NULL
FROM generate_series(1, 5000) AS g;
INSERT INTO catch_report (
id, fish_id, spot_id, waterbody_id, bait_id, weight_g, fishing_method,
caught_at, reported_at, player_name, source_type, source_url,
source_external_id, source_confidence, moderation_status, deleted_at, raw_payload
)
SELECT md5('report-' || g)::uuid,
md5('fish-' || ((g - 1) % 252 + 1))::uuid,
md5('spot-' || ((g - 1) % 5000 + 1))::uuid,
md5('water-' || (((g - 1) % 5000) % 19 + 1))::uuid,
md5('bait-' || ((g - 1) % 500 + 1))::uuid,
100 + (g * 97) % 50000,
(ARRAY['float', 'bottom', 'spinning'])[(g - 1) % 3 + 1],
clock_timestamp() - (((g * 97) % 7776000) * interval '1 second'),
clock_timestamp() - (((g * 97) % 7776000) * interval '1 second'),
'player-' || (g % 2000),
CASE WHEN g % 5 = 0 THEN 'official_record'::sourcetype ELSE 'user'::sourcetype END,
'https://example.invalid/catches/' || g,
'query-plan-' || g,
50 + g % 51,
CASE WHEN g % 10 = 1 THEN 'pending'::moderationstatus ELSE 'approved'::moderationstatus END,
CASE WHEN g % 50 = 0 THEN clock_timestamp() ELSE NULL END,
json_build_object('category', CASE WHEN g % 2 = 0 THEN 'weekly' ELSE 'absolute' END, 'region', 'RU')
FROM generate_series(1, 100000) AS g;
ANALYZE fish;
ANALYZE waterbody;
ANALYZE bait;
ANALYZE spot;
ANALYZE catch_report;
\echo 'DATASET'
SELECT count(*) AS reports,
count(*) FILTER (WHERE moderation_status = 'approved') AS approved,
count(*) FILTER (WHERE source_type = 'official_record') AS official,
count(DISTINCT spot_id) AS spots
FROM catch_report;
\echo 'PLAN activity_72h'
EXPLAIN (ANALYZE, BUFFERS, SETTINGS)
SELECT cr.*
FROM catch_report AS cr
LEFT JOIN fish AS f ON f.id = cr.fish_id
LEFT JOIN waterbody AS w ON w.id = cr.waterbody_id
LEFT JOIN spot AS s ON s.id = cr.spot_id
LEFT JOIN bait AS b ON b.id = cr.bait_id
WHERE cr.moderation_status = 'approved'
AND cr.deleted_at IS NULL
AND cr.spot_id IS NOT NULL
AND cr.reported_at >= now() - interval '72 hours';
\echo 'PLAN records_count'
EXPLAIN (ANALYZE, BUFFERS, SETTINGS)
SELECT count(cr.id)
FROM catch_report AS cr
WHERE cr.source_type = 'official_record';
\echo 'PLAN records_page'
EXPLAIN (ANALYZE, BUFFERS, SETTINGS)
SELECT cr.id, cr.fish_id, cr.waterbody_id, cr.bait_id, cr.weight_g, cr.caught_at
FROM catch_report AS cr
WHERE cr.source_type = 'official_record'
ORDER BY cr.caught_at DESC, cr.weight_g DESC, cr.id DESC
LIMIT 50;
\echo 'PLAN spot_detail'
EXPLAIN (ANALYZE, BUFFERS, SETTINGS)
SELECT cr.*
FROM catch_report AS cr
LEFT JOIN bait AS b ON b.id = cr.bait_id
WHERE cr.spot_id = md5('spot-2499')::uuid
AND cr.moderation_status = 'approved'
AND cr.deleted_at IS NULL;
\echo 'PLAN public_spot_pages'
EXPLAIN (ANALYZE, BUFFERS, SETTINGS)
SELECT DISTINCT w.slug, s.x, s.y, f.slug
FROM catch_report AS cr
JOIN spot AS s ON cr.spot_id = s.id
JOIN waterbody AS w ON s.waterbody_id = w.id
JOIN fish AS f ON cr.fish_id = f.id
WHERE cr.moderation_status = 'approved'
AND cr.deleted_at IS NULL
ORDER BY w.slug, s.x, s.y, f.slug
LIMIT 500;