Eigene Aggregatsfunktionen schreiben
Hans-Jürgen Schönig
www.postgresql-support.de
Hans-Jürgen Schönig
www.postgresql-supp...
Überblick
Hans-Jürgen Schönig
www.postgresql-support.de
Worum es gehen wird
Wie funktionieren PostgreSQL Aggregates?
Wie kann man einfache Aggregates schreiben?
Wie können Window...
Ein einfaches Aggregate
Ein Aggregate ist “etwas anders”
Eine “normale” Funktion gibt eine Zelle pro Aufruf retour
Ein Agg...
Ein einfache Beispiele:
“Normale” Funktionen geben eine Zeile pro Aufruf zurück:
SELECT md5(x::text) FROM generate_series(...
Einfache Beispiele:
Ein Aggregate macht aus vielen Zeilen eine Zeile:
SELECT sum(x) FROM generate_series(1, 3) AS x;
sum
-...
Eigene Aggregates schreiben
CREATE AGGREGATE name ( [ argmode ] [ argname ]
arg_data_type [ , ... ] ) (
SFUNC = sfunc, STY...
Unser erstes Ziel
Wir beginnen mit einfachen Stringoperationen
Damit lässt sich der Workflow einfach verdeutlichen
Komplexe...
Eine einfache Funktion
CREATE FUNCTION xagg(text, text) RETURNS text AS
$$
BEGIN
RAISE NOTICE 'xagg: "%" - adding %', $1, ...
Daraus kann man ein Aggregate machen
xagg wird für jede Zeile aufgerufen
CREATE AGGREGATE simpleagg(text) (
INITCOND = '',...
Ein Versuch
SELECT simpleagg(x::text)
FROM generate_series(1, 4) AS x;
NOTICE: xagg: "" - adding 1
NOTICE: xagg: "1" - add...
Kompliziertere Berechnungen
Zeilenoperationen reichen oft nicht aus
Um Berechnungen abzuschließen, kann eine FINALFUNC
defi...
Eine einfache FINALFUNC
CREATE FUNCTION sample_final(text) RETURNS text AS
$$
SELECT $1 || 'X';
$$ LANGUAGE 'sql';
CREATE ...
Die FINALFUNC in Action
test=# SELECT simpleagg(x::text)
FROM generate_series(1, 4) AS x;
NOTICE: xagg: "" - adding 1
NOTI...
Windowing und Analytics
Hans-Jürgen Schönig
www.postgresql-support.de
Aggregate und Analytics
Alle Aggregate können auch als Windows verwendet werden
Effizienz kann bei komplexeren Frame Clauses...
Ein Beispiel für schlechte Performance (1):
test=# SELECT x, simpleagg(x::text)
OVER (ORDER BY x ROWS BETWEEN
3 PRECEDING ...
Ein Beispiel für schlechte Performance (2):
NOTICE: xagg: "" - adding 2
NOTICE: xagg: "2" - adding 3
NOTICE: xagg: "23" - ...
Ein Beispiel für schlechte Performance (3):
x | simpleagg
---+-----------
1 | 1X
2 | 12X
3 | 123X
4 | 1234X
5 | 2345X
6 | ...
Funktionsaufrufe reduzieren
Das Ziel ist, die Anzahl der Funktionsaufrufe zu reduzieren.
Transition Functions helfen in di...
Wie das funktioniert
Wir benötigen eine MSFUNC und eine MINVFUNC
CREATE FUNCTION x_msfunc(text, text) RETURNS text AS $$
B...
Der zweite Teil des Aggregates
CREATE FUNCTION x_minvfunc(text, text) RETURNS text AS $$
BEGIN
RAISE NOTICE 'x_minvfunc: p...
Das Aggregat definieren
CREATE AGGREGATE myagg(text) (
stype = text,
sfunc = xagg,
initcond = '',
msfunc = x_msfunc,
minvfu...
Eine Demo-Abfrage
SELECT x, myagg(x::text) OVER (
PARTITION BY x % 2 ORDER BY x::text
ROWS BETWEEN CURRENT ROW AND 2 FOLLO...
Das Ergebnis sieht so aus
x | myagg
---+-------
1 | 135
2 | 246
3 | 357
4 | 468
5 | 579
6 | 68
7 | 79
8 | 8
9 | 9
(9 rows)...
Hinter den Kulissen passiert (1)
NOTICE: x_msfunc: / 2
NOTICE: x_msfunc: 2 / 4
NOTICE: x_msfunc: 24 / 6
NOTICE: x_minvfunc...
Was hinter den Kulissen passiert (2)
NOTICE: x_minvfunc: previous 135 / removing 1
NOTICE: x_msfunc: 35 / 7
NOTICE: x_minv...
Hypothetical Aggregates
Hans-Jürgen Schönig
www.postgresql-support.de
Was sind Hypothetical Aggregates?
Hypothetical Aggregates beantworten die “what if” Frage
Wie wäre das Ergebnis, würde ein...
Die Syntax für Ordered Sets
CREATE AGGREGATE name ( [ [ argmode ] [ argname ]
arg_data_type [ , ... ] ]
ORDER BY [ argmode...
Weitere Funktionen werden benötigt
Wieder benötigen wir eine SFUNC:
CREATE FUNCTION hypo_sfunc(text, text) RETURNS text AS...
Eine FINALFUNC
Eine Funktion wird wieder am Ende aufgerufen
CREATE FUNCTION hypo_final(text, text, text)
RETURNS text AS
$...
Die Definition des Aggregates
CREATE AGGREGATE whatif(text ORDER BY text) (
INITCOND = '',
STYPE = text,
SFUNC = hypo_sfunc...
Ein Beispiel
SELECT (x % 2)::text, whatif('abc')
WITHIN GROUP (ORDER BY x::text )
FROM generate_series(1, 4) AS x
GROUP BY...
Das Ergebnis
NOTICE: hypo_sfunc: / 2
NOTICE: hypo_sfunc: 2 / 4
NOTICE: hypo_final: 24 / abc / <NULL>
NOTICE: hypo_sfunc: /...
Finally . . .
Hans-Jürgen Schönig
www.postgresql-support.de
Gibt es Fragen?
Cybertec Schönig & Schönig GmbH
Gröhrmühlgasse 26
A-2700 Wiener Neustadt, Austria
www.postgresql-support.d...
Nächste SlideShare
Wird geladen in …5
×

PostgreSQL: Eigene Aggregate schreiben

524 Aufrufe

Veröffentlicht am

This talk describes how somebody can write his or her own PostgreSQL custom aggregation functions.
Hans also shows, how to run windowing functions and analytics to handle data in PostgreSQL.

Veröffentlicht in: Daten & Analysen
0 Kommentare
1 Gefällt mir
Statistik
Notizen
  • Als Erste(r) kommentieren

Keine Downloads
Aufrufe
Aufrufe insgesamt
524
Auf SlideShare
0
Aus Einbettungen
0
Anzahl an Einbettungen
9
Aktionen
Geteilt
0
Downloads
3
Kommentare
0
Gefällt mir
1
Einbettungen 0
Keine Einbettungen

Keine Notizen für die Folie

PostgreSQL: Eigene Aggregate schreiben

  1. 1. Eigene Aggregatsfunktionen schreiben Hans-Jürgen Schönig www.postgresql-support.de Hans-Jürgen Schönig www.postgresql-support.de
  2. 2. Überblick Hans-Jürgen Schönig www.postgresql-support.de
  3. 3. Worum es gehen wird Wie funktionieren PostgreSQL Aggregates? Wie kann man einfache Aggregates schreiben? Wie können Windowing Functions optimiert werden? Wie schreibt man Hypothetical Aggregates? Hans-Jürgen Schönig www.postgresql-support.de
  4. 4. Ein einfaches Aggregate Ein Aggregate ist “etwas anders” Eine “normale” Funktion gibt eine Zelle pro Aufruf retour Ein Aggregate gibt eine Zeile pro Gruppe zurück Hans-Jürgen Schönig www.postgresql-support.de
  5. 5. Ein einfache Beispiele: “Normale” Funktionen geben eine Zeile pro Aufruf zurück: SELECT md5(x::text) FROM generate_series(1, 3) AS x; md5 ---------------------------------- c4ca4238a0b923820dcc509a6f75849b c81e728d9d4c2f636f067f89cc14862c eccbc87e4b5ce2fe28308fd9f2a7baf3 (3 rows) Hans-Jürgen Schönig www.postgresql-support.de
  6. 6. Einfache Beispiele: Ein Aggregate macht aus vielen Zeilen eine Zeile: SELECT sum(x) FROM generate_series(1, 3) AS x; sum ----- 6 (1 row) Hans-Jürgen Schönig www.postgresql-support.de
  7. 7. Eigene Aggregates schreiben CREATE AGGREGATE name ( [ argmode ] [ argname ] arg_data_type [ , ... ] ) ( SFUNC = sfunc, STYPE = state_data_type [ , SSPACE = state_data_size ] [ , FINALFUNC = ffunc ] [ , FINALFUNC_EXTRA ] [ , INITCOND = initial_condition ] [ , MSFUNC = msfunc ] [ , MINVFUNC = minvfunc ] [ , MSTYPE = mstate_data_type ] [ , MSSPACE = mstate_data_size ] [ , MFINALFUNC = mffunc ] [ , MFINALFUNC_EXTRA ] [ , MINITCOND = minitial_condition ] [ , SORTOP = sort_operator ] ) Hans-Jürgen Schönig www.postgresql-support.de
  8. 8. Unser erstes Ziel Wir beginnen mit einfachen Stringoperationen Damit lässt sich der Workflow einfach verdeutlichen Komplexere Prozesse laufen nach dem selben Schema Hans-Jürgen Schönig www.postgresql-support.de
  9. 9. Eine einfache Funktion CREATE FUNCTION xagg(text, text) RETURNS text AS $$ BEGIN RAISE NOTICE 'xagg: "%" - adding %', $1, $2; RETURN $1 || $2; END; $$ LANGUAGE 'plpgsql'; Hans-Jürgen Schönig www.postgresql-support.de
  10. 10. Daraus kann man ein Aggregate machen xagg wird für jede Zeile aufgerufen CREATE AGGREGATE simpleagg(text) ( INITCOND = '', SFUNC = xagg, STYPE = text ); Hans-Jürgen Schönig www.postgresql-support.de
  11. 11. Ein Versuch SELECT simpleagg(x::text) FROM generate_series(1, 4) AS x; NOTICE: xagg: "" - adding 1 NOTICE: xagg: "1" - adding 2 NOTICE: xagg: "12" - adding 3 NOTICE: xagg: "123" - adding 4 simpleagg ----------- 1234 (1 row) Hans-Jürgen Schönig www.postgresql-support.de
  12. 12. Kompliziertere Berechnungen Zeilenoperationen reichen oft nicht aus Um Berechnungen abzuschließen, kann eine FINALFUNC definiert werden. Beispiel: avg dividiert am Ende die Summe durch die Anzahl Hans-Jürgen Schönig www.postgresql-support.de
  13. 13. Eine einfache FINALFUNC CREATE FUNCTION sample_final(text) RETURNS text AS $$ SELECT $1 || 'X'; $$ LANGUAGE 'sql'; CREATE AGGREGATE simpleagg(text) ( INITCOND = '', SFUNC = xagg, FINALFUNC = sample_final, STYPE = text ); Hans-Jürgen Schönig www.postgresql-support.de
  14. 14. Die FINALFUNC in Action test=# SELECT simpleagg(x::text) FROM generate_series(1, 4) AS x; NOTICE: xagg: "" - adding 1 NOTICE: xagg: "1" - adding 2 NOTICE: xagg: "12" - adding 3 NOTICE: xagg: "123" - adding 4 simpleagg ----------- 1234X (1 row) Hans-Jürgen Schönig www.postgresql-support.de
  15. 15. Windowing und Analytics Hans-Jürgen Schönig www.postgresql-support.de
  16. 16. Aggregate und Analytics Alle Aggregate können auch als Windows verwendet werden Effizienz kann bei komplexeren Frame Clauses ein Thema werden SELECT ... OVER (ORDER BY ... ROWS BETWEEN x PREDECING AND y FOLLOWING) ... Hans-Jürgen Schönig www.postgresql-support.de
  17. 17. Ein Beispiel für schlechte Performance (1): test=# SELECT x, simpleagg(x::text) OVER (ORDER BY x ROWS BETWEEN 3 PRECEDING AND 0 FOLLOWING ) FROM generate_series(1, 6) AS x; NOTICE: xagg: "" - adding 1 NOTICE: xagg: "1" - adding 2 NOTICE: xagg: "12" - adding 3 NOTICE: xagg: "123" - adding 4 Hans-Jürgen Schönig www.postgresql-support.de
  18. 18. Ein Beispiel für schlechte Performance (2): NOTICE: xagg: "" - adding 2 NOTICE: xagg: "2" - adding 3 NOTICE: xagg: "23" - adding 4 NOTICE: xagg: "234" - adding 5 NOTICE: xagg: "" - adding 3 NOTICE: xagg: "3" - adding 4 NOTICE: xagg: "34" - adding 5 NOTICE: xagg: "345" - adding 6 Hans-Jürgen Schönig www.postgresql-support.de
  19. 19. Ein Beispiel für schlechte Performance (3): x | simpleagg ---+----------- 1 | 1X 2 | 12X 3 | 123X 4 | 1234X 5 | 2345X 6 | 3456X (6 rows) => Die Anzahl der Funktionsaufrufe ist explodiert Hans-Jürgen Schönig www.postgresql-support.de
  20. 20. Funktionsaufrufe reduzieren Das Ziel ist, die Anzahl der Funktionsaufrufe zu reduzieren. Transition Functions helfen in diesem Fall. Transition Functions sind seit PostgreSQL 9.4 möglich Hans-Jürgen Schönig www.postgresql-support.de
  21. 21. Wie das funktioniert Wir benötigen eine MSFUNC und eine MINVFUNC CREATE FUNCTION x_msfunc(text, text) RETURNS text AS $$ BEGIN RAISE NOTICE 'x_msfunc: % / %', $1, $2; RETURN $1 || $2; END; $$ LANGUAGE 'plpgsql'; Hans-Jürgen Schönig www.postgresql-support.de
  22. 22. Der zweite Teil des Aggregates CREATE FUNCTION x_minvfunc(text, text) RETURNS text AS $$ BEGIN RAISE NOTICE 'x_minvfunc: previous % / removing %', $1, $2; RETURN substring($1, 2, length($1) - 1); END; $$ LANGUAGE 'plpgsql'; Hans-Jürgen Schönig www.postgresql-support.de
  23. 23. Das Aggregat definieren CREATE AGGREGATE myagg(text) ( stype = text, sfunc = xagg, initcond = '', msfunc = x_msfunc, minvfunc = x_minvfunc, mstype = text, MINITCOND = '' ); Die Logik ist sehr ähnlich wie vorher Eine der Funktionen wird für jede Zeile aufgerufen. Ein optionaler Funktionsaufruf passiert am Ende. Hans-Jürgen Schönig www.postgresql-support.de
  24. 24. Eine Demo-Abfrage SELECT x, myagg(x::text) OVER ( PARTITION BY x % 2 ORDER BY x::text ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING) FROM generate_series(1, 9) AS x ORDER BY x; Hans-Jürgen Schönig www.postgresql-support.de
  25. 25. Das Ergebnis sieht so aus x | myagg ---+------- 1 | 135 2 | 246 3 | 357 4 | 468 5 | 579 6 | 68 7 | 79 8 | 8 9 | 9 (9 rows) Hans-Jürgen Schönig www.postgresql-support.de
  26. 26. Hinter den Kulissen passiert (1) NOTICE: x_msfunc: / 2 NOTICE: x_msfunc: 2 / 4 NOTICE: x_msfunc: 24 / 6 NOTICE: x_minvfunc: previous 246 / removing 2 NOTICE: x_msfunc: 46 / 8 NOTICE: x_minvfunc: previous 468 / removing 4 NOTICE: x_minvfunc: previous 68 / removing 6 NOTICE: x_msfunc: / 1 NOTICE: x_msfunc: 1 / 3 NOTICE: x_msfunc: 13 / 5 Hans-Jürgen Schönig www.postgresql-support.de
  27. 27. Was hinter den Kulissen passiert (2) NOTICE: x_minvfunc: previous 135 / removing 1 NOTICE: x_msfunc: 35 / 7 NOTICE: x_minvfunc: previous 357 / removing 3 NOTICE: x_msfunc: 57 / 9 NOTICE: x_minvfunc: previous 579 / removing 5 NOTICE: x_minvfunc: previous 79 / removing 7 Hans-Jürgen Schönig www.postgresql-support.de
  28. 28. Hypothetical Aggregates Hans-Jürgen Schönig www.postgresql-support.de
  29. 29. Was sind Hypothetical Aggregates? Hypothetical Aggregates beantworten die “what if” Frage Wie wäre das Ergebnis, würde ein bestimmter Wert existieren? Ein klassisches Beispiel: test=# SELECT x % 2 AS odd_even, rank(5) WITHIN GROUP (ORDER BY x) FROM generate_series(1, 10) AS x GROUP BY 1; odd_even | rank ----------+------ 0 | 3 1 | 3 (2 rows) Hans-Jürgen Schönig www.postgresql-support.de
  30. 30. Die Syntax für Ordered Sets CREATE AGGREGATE name ( [ [ argmode ] [ argname ] arg_data_type [ , ... ] ] ORDER BY [ argmode ] [ argname ] arg_data_type [ , ... ] ) ( SFUNC = sfunc, STYPE = state_data_type [ , SSPACE = state_data_size ] [ , FINALFUNC = ffunc ] [ , FINALFUNC_EXTRA ] [ , INITCOND = initial_condition ] [ , HYPOTHETICAL ] ) Hans-Jürgen Schönig www.postgresql-support.de
  31. 31. Weitere Funktionen werden benötigt Wieder benötigen wir eine SFUNC: CREATE FUNCTION hypo_sfunc(text, text) RETURNS text AS $$ BEGIN RAISE NOTICE 'hypo_sfunc: % / %', $1, $2; RETURN $1 || $2; END; $$ LANGUAGE 'plpgsql'; Hans-Jürgen Schönig www.postgresql-support.de
  32. 32. Eine FINALFUNC Eine Funktion wird wieder am Ende aufgerufen CREATE FUNCTION hypo_final(text, text, text) RETURNS text AS $$ BEGIN RAISE NOTICE 'hypo_final: % / % / %', $1, $2, $3; RETURN $1 || $2; END; $$ LANGUAGE 'plpgsql'; Hans-Jürgen Schönig www.postgresql-support.de
  33. 33. Die Definition des Aggregates CREATE AGGREGATE whatif(text ORDER BY text) ( INITCOND = '', STYPE = text, SFUNC = hypo_sfunc, FINALFUNC = hypo_final, FINALFUNC_EXTRA = true, HYPOTHETICAL ); Hans-Jürgen Schönig www.postgresql-support.de
  34. 34. Ein Beispiel SELECT (x % 2)::text, whatif('abc') WITHIN GROUP (ORDER BY x::text ) FROM generate_series(1, 4) AS x GROUP BY 1; Hans-Jürgen Schönig www.postgresql-support.de
  35. 35. Das Ergebnis NOTICE: hypo_sfunc: / 2 NOTICE: hypo_sfunc: 2 / 4 NOTICE: hypo_final: 24 / abc / <NULL> NOTICE: hypo_sfunc: / 1 NOTICE: hypo_sfunc: 1 / 3 NOTICE: hypo_final: 13 / abc / <NULL> text | whatif ------+-------- 0 | 24abc 1 | 13abc (2 rows) Hans-Jürgen Schönig www.postgresql-support.de
  36. 36. Finally . . . Hans-Jürgen Schönig www.postgresql-support.de
  37. 37. Gibt es Fragen? Cybertec Schönig & Schönig GmbH Gröhrmühlgasse 26 A-2700 Wiener Neustadt, Austria www.postgresql-support.de Email: hs@cybertec.at Hans-Jürgen Schönig www.postgresql-support.de

×