[Performance/DB] Fehlende Indizes auf Fremdschluesseln #51

Closed
opened 2026-09-09 20:17:02 +00:00 by Aceless · 1 comment
Owner

Problem

backend/database_definition.sql legt nur einen einzigen Index an (idx_instruction_recipe). Alle anderen Fremdschluessel sind unindiziert, obwohl genau ueber sie abgefragt wird.

Fehlend

CREATE INDEX IF NOT EXISTS idx_ingredient_recipe        ON ingredient(recipe_id);
CREATE INDEX IF NOT EXISTS idx_recipe_image_recipe      ON recipe_image(recipe_id);
CREATE INDEX IF NOT EXISTS idx_recipe_space             ON recipe(space_id);
CREATE INDEX IF NOT EXISTS idx_meal_plan_entry_plan     ON meal_plan_entry(meal_plan_id);
CREATE INDEX IF NOT EXISTS idx_meal_plan_entry_recipe   ON meal_plan_entry(recipe_id);
CREATE INDEX IF NOT EXISTS idx_space_user_user          ON space_user(user_id);
CREATE INDEX IF NOT EXISTS idx_weekly_meal_plan_space   ON weekly_meal_plan(space_id, week_start);

space_user hat den Primaerschluessel (space_id, user_id). Die Abfrage "alle Spaces eines Benutzers" (GetSpacesByUserIdAsync) filtert aber auf user_id und kann den Index deshalb nicht nutzen.

Nebenpunkt

Es gibt kein Migrationswerkzeug. database_definition.sql ist ein pgAdmin-Export und beschreibt nur den Ist-Zustand. Ein Migrationsordner mit nummerierten Skripten (oder DbUp/FluentMigrator) waere sinnvoll, damit solche Aenderungen nachvollziehbar ausgerollt werden.

## Problem `backend/database_definition.sql` legt nur einen einzigen Index an (`idx_instruction_recipe`). Alle anderen Fremdschluessel sind unindiziert, obwohl genau ueber sie abgefragt wird. ## Fehlend ```sql CREATE INDEX IF NOT EXISTS idx_ingredient_recipe ON ingredient(recipe_id); CREATE INDEX IF NOT EXISTS idx_recipe_image_recipe ON recipe_image(recipe_id); CREATE INDEX IF NOT EXISTS idx_recipe_space ON recipe(space_id); CREATE INDEX IF NOT EXISTS idx_meal_plan_entry_plan ON meal_plan_entry(meal_plan_id); CREATE INDEX IF NOT EXISTS idx_meal_plan_entry_recipe ON meal_plan_entry(recipe_id); CREATE INDEX IF NOT EXISTS idx_space_user_user ON space_user(user_id); CREATE INDEX IF NOT EXISTS idx_weekly_meal_plan_space ON weekly_meal_plan(space_id, week_start); ``` `space_user` hat den Primaerschluessel `(space_id, user_id)`. Die Abfrage "alle Spaces eines Benutzers" (`GetSpacesByUserIdAsync`) filtert aber auf `user_id` und kann den Index deshalb nicht nutzen. ## Nebenpunkt Es gibt kein Migrationswerkzeug. `database_definition.sql` ist ein pgAdmin-Export und beschreibt nur den Ist-Zustand. Ein Migrationsordner mit nummerierten Skripten (oder DbUp/FluentMigrator) waere sinnvoll, damit solche Aenderungen nachvollziehbar ausgerollt werden.
Author
Owner

Erledigt in backend/migrations/001_constraints_and_indexes.sql.

Angelegt werden Indizes auf ingredient(recipe_id), recipe_image(recipe_id), recipe(space_id), recipe_tag(recipe_id), recipe_suitable_for(recipe_id), meal_plan_entry(meal_plan_id), meal_plan_entry(recipe_id), weekly_meal_plan(space_id, week_start), space_user(user_id) und space(owner_id).

Dazu ein eindeutiger Index auf lower(email), der übersprungen wird, solange es kollidierende Konten gibt. Die Suche nach der E-Mail läuft passend dazu über lower(email) = lower(@Email), damit vorhandene Konten mit Großbuchstaben weiter gefunden werden.

Nebenbefund, ebenfalls behoben: database_definition.sql enthielt die Enum-Typen meal_type, difficulty_level und space_role nicht. Das Skript ließ sich auf einer leeren Datenbank nicht ausführen, es fehlte genau der Teil, den die Tabellen brauchen. Die CREATE TYPE-Anweisungen stehen jetzt am Anfang der Datei.

Die Migration wurde auf einer frischen PostgreSQL-16-Datenbank getestet.


Branch backend/issue-fixes, Commits 90183ae.

Erledigt in `backend/migrations/001_constraints_and_indexes.sql`. Angelegt werden Indizes auf `ingredient(recipe_id)`, `recipe_image(recipe_id)`, `recipe(space_id)`, `recipe_tag(recipe_id)`, `recipe_suitable_for(recipe_id)`, `meal_plan_entry(meal_plan_id)`, `meal_plan_entry(recipe_id)`, `weekly_meal_plan(space_id, week_start)`, `space_user(user_id)` und `space(owner_id)`. Dazu ein eindeutiger Index auf `lower(email)`, der übersprungen wird, solange es kollidierende Konten gibt. Die Suche nach der E-Mail läuft passend dazu über `lower(email) = lower(@Email)`, damit vorhandene Konten mit Großbuchstaben weiter gefunden werden. **Nebenbefund, ebenfalls behoben:** `database_definition.sql` enthielt die Enum-Typen `meal_type`, `difficulty_level` und `space_role` nicht. Das Skript ließ sich auf einer leeren Datenbank nicht ausführen, es fehlte genau der Teil, den die Tabellen brauchen. Die `CREATE TYPE`-Anweisungen stehen jetzt am Anfang der Datei. Die Migration wurde auf einer frischen PostgreSQL-16-Datenbank getestet. --- Branch `backend/issue-fixes`, Commits 90183ae.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Aceless/RecipePlanner#51
No description provided.