Playwright-Projekt perf (nur mit PERF_WEB_URL, nur lesend, nie in der CI): CDP-Drosselung 100 ms / 10 Mbit/s, mind. 100 Suchen, Messung im Browser vom letzten Tastendruck bis zur ersten Kachel. Ladeskript fuer synthetisches Volumen unter supabase/perf/. Messung und Aussagegrenzen in der Umsetzungsdoku. Refs #3 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
116 lines
5.5 KiB
PL/PgSQL
116 lines
5.5 KiB
PL/PgSQL
-- Synthetisches Katalogvolumen fuer die Latenzmessung KAT-01 Kriterium 7 (Playwright-Projekt `perf`,
|
|
-- Spec #3 Abschnitt 7.3). Anders als catalog_search_perf.sql (Messung in der Datenbank, Rollback) wird hier
|
|
-- COMMITTET: Die App im Browser muss die Daten ueber Kong lesen koennen. Deshalb nur lokal, nur kurz, und immer
|
|
-- mit catalog_search_perf_unload.sql wieder entfernen.
|
|
--
|
|
-- Was es tut: legt 10 000 sichtbare Katalogspiele (Standard), je zwei alternative Titel, 2 000 Verlage
|
|
-- (12 900 Zuordnungen) und je Spiel zwei Genres und drei Mechaniken aus dem VORHANDENEN Vokabular an. Alle Spiele
|
|
-- und Verlage tragen IDs mit dem Praefix 9e4f0000- , das Entfernen loescht darueber (Zuordnungen und alternative
|
|
-- Titel haengen per on delete cascade an den Spielen). Danach vacuum (analyze), damit der Planer die echten
|
|
-- Groessen kennt.
|
|
--
|
|
-- Schutz wie in catalog_search_perf.sql: -v confirm_local=yes, nur per Unix-Socket (docker exec ... psql), Abbruch
|
|
-- bei mehr als 20 privaten Spielen. (Konten werden bewusst NICHT gezaehlt: die E2E-Tests legen laufend welche an.)
|
|
-- Aufruf:
|
|
-- docker exec -i supabase_db_shuffle psql -U postgres -d postgres -X -v confirm_local=yes -v n_games=10000 \
|
|
-- < supabase/perf/catalog_search_perf_load.sql
|
|
\set ON_ERROR_STOP on
|
|
\if :{?confirm_local}
|
|
\else
|
|
\set confirm_local no
|
|
\endif
|
|
select :'confirm_local' = 'yes' as confirm_ok, coalesce(:'HOST', '') like '/%' as socket_ok \gset
|
|
\if :confirm_ok
|
|
\else
|
|
\echo 'Abbruch: mit -v confirm_local=yes aufrufen (nur lokal, siehe Kopfkommentar).'
|
|
\quit
|
|
\endif
|
|
\if :socket_ok
|
|
\else
|
|
\echo 'Abbruch: nur per Unix-Socket im lokalen Container (docker exec ... psql), nie ueber TCP gegen einen Server.'
|
|
\quit
|
|
\endif
|
|
\if :{?n_games}
|
|
\else
|
|
\set n_games 10000
|
|
\endif
|
|
|
|
do $guard$
|
|
begin
|
|
if (select count(*) from public.games where visibility = 'private') > 20 then
|
|
raise exception 'Abbruch: Die Datenbank sieht nach echten Daten aus (mehr als 20 private Spiele). Nur lokal.';
|
|
end if;
|
|
if exists (select 1 from public.games where id::text like '9e4f0000-%') then
|
|
raise exception 'Abbruch: synthetische Daten sind schon geladen (erst catalog_search_perf_unload.sql ausfuehren).';
|
|
end if;
|
|
if (select count(*) from public.genres) < 3 or (select count(*) from public.mechanics) < 3 then
|
|
raise exception 'Abbruch: Genre-/Mechanik-Vokabular fehlt (supabase db reset einspielen).';
|
|
end if;
|
|
end
|
|
$guard$;
|
|
|
|
begin;
|
|
select setseed(0.42);
|
|
|
|
create temp table perf_words on commit drop as
|
|
select i, translate(substr(md5('w' || i), 1, 4 + (i % 6)), '0123456789', 'ghijklmnop') as w
|
|
from generate_series(1, 3000) i;
|
|
alter table perf_words add primary key (i);
|
|
create function pg_temp.pick() returns text language sql volatile as
|
|
$$ select w from perf_words where i = (select 1 + floor(power(random(), 2.2) * 3000)::int) $$;
|
|
|
|
insert into public.publishers (id, name)
|
|
select ('9e4f0000-0000-4000-9000-' || lpad(to_hex(i), 12, '0'))::uuid, initcap(pg_temp.pick()) || ' Spiele ' || i
|
|
from generate_series(1, 2000) i;
|
|
|
|
insert into public.games (id, title, visibility, year, min_players, max_players, min_minutes, max_minutes, min_age, description, description_locale)
|
|
select ('9e4f0000-0000-4000-8000-' || lpad(to_hex(g), 12, '0'))::uuid,
|
|
initcap(concat_ws(' ', pg_temp.pick(), case when k >= 2 then pg_temp.pick() end, case when k >= 3 then pg_temp.pick() end,
|
|
case when k >= 4 then pg_temp.pick() end)),
|
|
'catalog', 1990 + (g % 35), mn, mn + (g % 5), 10 + (g % 12) * 10, 30 + (g % 12) * 10, 6 + (g % 4) * 3,
|
|
'Synthetischer Kurztext ' || g, 'de'
|
|
from (select g, 1 + floor(random() * 3.99)::int as k, 1 + (g % 4) as mn from generate_series(1, :n_games) g) s;
|
|
|
|
insert into public.game_alt_titles (game_id, locale, title)
|
|
select g.id, l.locale, initcap(pg_temp.pick() || ' ' || pg_temp.pick())
|
|
from public.games g, (values ('de'), ('en')) as l(locale)
|
|
where g.id::text like '9e4f0000-%'
|
|
on conflict do nothing;
|
|
|
|
insert into public.game_publishers (game_id, publisher_id)
|
|
select g.id, p.id
|
|
from public.games g
|
|
cross join lateral (select id from public.publishers where id::text like '9e4f0000-%'
|
|
order by md5(g.id::text || id::text) limit 1) p
|
|
where g.id::text like '9e4f0000-%'
|
|
on conflict do nothing;
|
|
insert into public.game_publishers (game_id, publisher_id)
|
|
select g.id, p.id
|
|
from public.games g
|
|
cross join lateral (select id from public.publishers where id::text like '9e4f0000-%'
|
|
order by md5(g.id::text || id::text || 'b') limit 1) p
|
|
where g.id::text like '9e4f0000-%' and random() < 0.3
|
|
on conflict do nothing;
|
|
|
|
insert into public.game_genres (game_id, genre_id)
|
|
select g.id, t.id from public.games g cross join lateral
|
|
(select x.id from public.genres x order by md5(g.id::text || x.id::text) limit 2) t
|
|
where g.id::text like '9e4f0000-%' on conflict do nothing;
|
|
insert into public.game_mechanics (game_id, mechanic_id)
|
|
select g.id, t.id from public.games g cross join lateral
|
|
(select x.id from public.mechanics x order by md5(g.id::text || x.id::text) limit 3) t
|
|
where g.id::text like '9e4f0000-%' on conflict do nothing;
|
|
commit;
|
|
|
|
vacuum (analyze) public.games;
|
|
vacuum (analyze) public.game_alt_titles;
|
|
vacuum (analyze) public.publishers;
|
|
vacuum (analyze) public.game_publishers;
|
|
vacuum (analyze) public.game_genres;
|
|
vacuum (analyze) public.game_mechanics;
|
|
|
|
\echo === geladen ===
|
|
select (select count(*) from public.catalog_games) as katalogspiele,
|
|
(select count(*) from public.game_alt_titles) as alt_titel,
|
|
(select count(*) from public.publishers) as verlage,
|
|
(select count(*) from public.game_publishers) as verlag_zuordnungen;
|