Die Akte brauchte 1,3 bis 1,5 s, davon ueber 1,1 s in dieser Funktion.
Als postgres -- am Zeilenschutz vorbei -- kostet dieselbe Funktion 60 ms.
als postgres 60 ms
als alpenwerk_app, vor 20260924200000 1457 ms
als alpenwerk_app, danach 1153 ms
Die vorige Migration fasste die Policies so, dass is_hr_user() je Abfrage
einmal laeuft. Das half um ein Fuenftel -- die Pruefung war also nicht der
Hauptposten.
Die Teile der Funktion sind einzeln billig, unter Zeilenschutz gemessen:
Besetzungen 12 ms, Vorfahrenkette 7 ms, Leitungen 9 ms. Zusammen 28 ms,
die Funktion daraus 1153. Die Kosten entstehen beim Zusammensetzen: unter
Zeilenschutz wird aus jeder Tabellenreferenz eine Unterabfrage mit
Sicherheitsschranke, und der Planer verliert die Freiheit, die
Zwischenmengen einmal zu berechnen -- die beiden Unterabfragen am Ende
laufen dann fuer jede der 784 Zeilen erneut.
Jetzt security definer mit require_hr_admin() in der ersten Zeile. Das ist
dieselbe Bedingung, die in den Policies aller vier gelesenen Tabellen
steht -- require_hr_admin() ist woertlich "if not is_hr_user() then
raise". Sie wird einmal gestellt statt hunderttausendfach. Wer Daten
bekommt, aendert sich nicht; eine unberechtigte Anfrage bekommt jetzt eine
Meldung statt einer leeren Antwort.
Der Preis: diese Funktion liest die vier Tabellen am Zeilenschutz vorbei.
Kaeme je eine feinere Rechteordnung, muesste sie eigens nachgezogen
werden. Mit dem Eigentuemer besprochen -- solche Rollen sind nicht
vorgesehen.
Der Koerper ist unveraendert aus 20260727120100, der einzigen textlichen
Fassung. Geaendert sind Sprache, security definer, search_path und die
erste Zeile.