SlideShare a Scribd company logo
1 of 37
Download to read offline
Eigene Aggregatsfunktionen schreiben
Hans-Jürgen Schönig
www.postgresql-support.de
Hans-Jürgen Schönig
www.postgresql-support.de
Ü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 Windowing Functions optimiert werden?
Wie schreibt man Hypothetical Aggregates?
Hans-Jürgen Schönig
www.postgresql-support.de
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
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
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
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
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
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
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
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
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
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
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
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 Thema
werden
SELECT ...
OVER (ORDER BY ...
ROWS BETWEEN x PREDECING AND y FOLLOWING) ...
Hans-Jürgen Schönig
www.postgresql-support.de
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
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
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
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
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
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
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
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
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
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
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
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 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
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
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
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
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
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
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
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.de
Email: hs@cybertec.at
Hans-Jürgen Schönig
www.postgresql-support.de

More Related Content

What's hot

SysDig Metriken zentralisieren
SysDig Metriken zentralisierenSysDig Metriken zentralisieren
SysDig Metriken zentralisiereninovex GmbH
 
Introduction into Oracle Data Pump 11g/12c - Export and Import Data
Introduction into Oracle Data Pump 11g/12c - Export and Import DataIntroduction into Oracle Data Pump 11g/12c - Export and Import Data
Introduction into Oracle Data Pump 11g/12c - Export and Import DataGunther Pippèrr
 
Oracle workshop sessiontracing
Oracle workshop sessiontracingOracle workshop sessiontracing
Oracle workshop sessiontracingciganek
 

What's hot (6)

JavaScript Performance
JavaScript PerformanceJavaScript Performance
JavaScript Performance
 
SysDig Metriken zentralisieren
SysDig Metriken zentralisierenSysDig Metriken zentralisieren
SysDig Metriken zentralisieren
 
check_sap_health
check_sap_healthcheck_sap_health
check_sap_health
 
Introduction into Oracle Data Pump 11g/12c - Export and Import Data
Introduction into Oracle Data Pump 11g/12c - Export and Import DataIntroduction into Oracle Data Pump 11g/12c - Export and Import Data
Introduction into Oracle Data Pump 11g/12c - Export and Import Data
 
Oracle workshop sessiontracing
Oracle workshop sessiontracingOracle workshop sessiontracing
Oracle workshop sessiontracing
 
Ldap sqlnet
Ldap sqlnetLdap sqlnet
Ldap sqlnet
 

Viewers also liked

Walbouncer: Filtering PostgreSQL transaction log
Walbouncer: Filtering PostgreSQL transaction logWalbouncer: Filtering PostgreSQL transaction log
Walbouncer: Filtering PostgreSQL transaction logHans-Jürgen Schönig
 
PostgreSQL: Joining 1 million tables
PostgreSQL: Joining 1 million tablesPostgreSQL: Joining 1 million tables
PostgreSQL: Joining 1 million tablesHans-Jürgen Schönig
 
PostgreSQL instance encryption: More database security
PostgreSQL instance encryption: More database securityPostgreSQL instance encryption: More database security
PostgreSQL instance encryption: More database securityHans-Jürgen Schönig
 
PostgreSQL: Data analysis and analytics
PostgreSQL: Data analysis and analyticsPostgreSQL: Data analysis and analytics
PostgreSQL: Data analysis and analyticsHans-Jürgen Schönig
 

Viewers also liked (7)

Walbouncer: Filtering PostgreSQL transaction log
Walbouncer: Filtering PostgreSQL transaction logWalbouncer: Filtering PostgreSQL transaction log
Walbouncer: Filtering PostgreSQL transaction log
 
PostgreSQL: The NoSQL way
PostgreSQL: The NoSQL wayPostgreSQL: The NoSQL way
PostgreSQL: The NoSQL way
 
PostgreSQL: Joining 1 million tables
PostgreSQL: Joining 1 million tablesPostgreSQL: Joining 1 million tables
PostgreSQL: Joining 1 million tables
 
PostgreSQL instance encryption: More database security
PostgreSQL instance encryption: More database securityPostgreSQL instance encryption: More database security
PostgreSQL instance encryption: More database security
 
PostgreSQL Replication Tutorial
PostgreSQL Replication TutorialPostgreSQL Replication Tutorial
PostgreSQL Replication Tutorial
 
PostgreSQL: Advanced indexing
PostgreSQL: Advanced indexingPostgreSQL: Advanced indexing
PostgreSQL: Advanced indexing
 
PostgreSQL: Data analysis and analytics
PostgreSQL: Data analysis and analyticsPostgreSQL: Data analysis and analytics
PostgreSQL: Data analysis and analytics
 

Similar to PostgreSQL: Eigene Aggregate schreiben

Mehr Dynamik Durch Skriptsprachen
Mehr Dynamik Durch SkriptsprachenMehr Dynamik Durch Skriptsprachen
Mehr Dynamik Durch Skriptsprachenjlink
 
ApEx effektiv - DOAG 2010 - OPITZ CONSULTING - Stephan Engel
ApEx effektiv - DOAG 2010 - OPITZ CONSULTING - Stephan EngelApEx effektiv - DOAG 2010 - OPITZ CONSULTING - Stephan Engel
ApEx effektiv - DOAG 2010 - OPITZ CONSULTING - Stephan EngelOPITZ CONSULTING Deutschland
 
.NET Summit 2016 München: EcmaScript 2015+ with TypeScript
.NET Summit 2016 München: EcmaScript 2015+ with TypeScript.NET Summit 2016 München: EcmaScript 2015+ with TypeScript
.NET Summit 2016 München: EcmaScript 2015+ with TypeScriptManfred Steyer
 
Differenzial Analyse in der Praxis (Florian Walther)
Differenzial Analyse in der Praxis (Florian Walther)Differenzial Analyse in der Praxis (Florian Walther)
Differenzial Analyse in der Praxis (Florian Walther)GEEKcon
 
Drupal 8: TWIG Template Engine
Drupal 8:  TWIG Template EngineDrupal 8:  TWIG Template Engine
Drupal 8: TWIG Template Enginedrubb
 
Shortcodes erstellen mit WordPress
Shortcodes erstellen mit WordPressShortcodes erstellen mit WordPress
Shortcodes erstellen mit WordPressTorsten Landsiedel
 
Java Streams und Lambdas
Java Streams und LambdasJava Streams und Lambdas
Java Streams und LambdasNane Kratzke
 
Jpgraph - eine Einführung
Jpgraph - eine EinführungJpgraph - eine Einführung
Jpgraph - eine Einführungfrankstaude
 
Go - Googles Sprache für skalierbare Systeme
Go - Googles Sprache für skalierbare SystemeGo - Googles Sprache für skalierbare Systeme
Go - Googles Sprache für skalierbare SystemeFrank Müller
 
Migrationspfade für Angular 2
Migrationspfade für Angular 2Migrationspfade für Angular 2
Migrationspfade für Angular 2Manfred Steyer
 
TYPO3 CMS 7.3 - Die Neuerungen - pluswerk
TYPO3 CMS 7.3 - Die Neuerungen - pluswerkTYPO3 CMS 7.3 - Die Neuerungen - pluswerk
TYPO3 CMS 7.3 - Die Neuerungen - pluswerkdie.agilen GmbH
 
Apache CouchDB at PHPUG Karlsruhe, Germany (Jan 27th 2009)
Apache CouchDB at PHPUG Karlsruhe, Germany (Jan 27th 2009)Apache CouchDB at PHPUG Karlsruhe, Germany (Jan 27th 2009)
Apache CouchDB at PHPUG Karlsruhe, Germany (Jan 27th 2009)Nils Adermann
 
Webcon 2012 Mobile Development mit Sencha Touch
Webcon 2012  Mobile Development mit Sencha TouchWebcon 2012  Mobile Development mit Sencha Touch
Webcon 2012 Mobile Development mit Sencha TouchThorsten Suckow-Homberg
 
PureSQL APEX Connect
PureSQL APEX ConnectPureSQL APEX Connect
PureSQL APEX ConnectTrivadis
 
Pure SQL for batch processing
Pure SQL for batch processingPure SQL for batch processing
Pure SQL for batch processingAndrej Pashchenko
 
Modern angular 02_angular_mit_type_script
Modern angular 02_angular_mit_type_scriptModern angular 02_angular_mit_type_script
Modern angular 02_angular_mit_type_scriptManfred Steyer
 
Prototype 1.7
Prototype 1.7Prototype 1.7
Prototype 1.7msebel
 
Funktionale Programmierung und mehr mit Scala
Funktionale Programmierung und mehr mit ScalaFunktionale Programmierung und mehr mit Scala
Funktionale Programmierung und mehr mit Scalathoherr
 

Similar to PostgreSQL: Eigene Aggregate schreiben (20)

Mehr Dynamik Durch Skriptsprachen
Mehr Dynamik Durch SkriptsprachenMehr Dynamik Durch Skriptsprachen
Mehr Dynamik Durch Skriptsprachen
 
ApEx effektiv - DOAG 2010 - OPITZ CONSULTING - Stephan Engel
ApEx effektiv - DOAG 2010 - OPITZ CONSULTING - Stephan EngelApEx effektiv - DOAG 2010 - OPITZ CONSULTING - Stephan Engel
ApEx effektiv - DOAG 2010 - OPITZ CONSULTING - Stephan Engel
 
.NET Summit 2016 München: EcmaScript 2015+ with TypeScript
.NET Summit 2016 München: EcmaScript 2015+ with TypeScript.NET Summit 2016 München: EcmaScript 2015+ with TypeScript
.NET Summit 2016 München: EcmaScript 2015+ with TypeScript
 
Differenzial Analyse in der Praxis (Florian Walther)
Differenzial Analyse in der Praxis (Florian Walther)Differenzial Analyse in der Praxis (Florian Walther)
Differenzial Analyse in der Praxis (Florian Walther)
 
Drupal 8: TWIG Template Engine
Drupal 8:  TWIG Template EngineDrupal 8:  TWIG Template Engine
Drupal 8: TWIG Template Engine
 
Shortcodes erstellen mit WordPress
Shortcodes erstellen mit WordPressShortcodes erstellen mit WordPress
Shortcodes erstellen mit WordPress
 
Java Streams und Lambdas
Java Streams und LambdasJava Streams und Lambdas
Java Streams und Lambdas
 
Jpgraph - eine Einführung
Jpgraph - eine EinführungJpgraph - eine Einführung
Jpgraph - eine Einführung
 
Go - Googles Sprache für skalierbare Systeme
Go - Googles Sprache für skalierbare SystemeGo - Googles Sprache für skalierbare Systeme
Go - Googles Sprache für skalierbare Systeme
 
Migrationspfade für Angular 2
Migrationspfade für Angular 2Migrationspfade für Angular 2
Migrationspfade für Angular 2
 
TypeScript
TypeScriptTypeScript
TypeScript
 
TYPO3 CMS 7.3 - Die Neuerungen - pluswerk
TYPO3 CMS 7.3 - Die Neuerungen - pluswerkTYPO3 CMS 7.3 - Die Neuerungen - pluswerk
TYPO3 CMS 7.3 - Die Neuerungen - pluswerk
 
Apache CouchDB at PHPUG Karlsruhe, Germany (Jan 27th 2009)
Apache CouchDB at PHPUG Karlsruhe, Germany (Jan 27th 2009)Apache CouchDB at PHPUG Karlsruhe, Germany (Jan 27th 2009)
Apache CouchDB at PHPUG Karlsruhe, Germany (Jan 27th 2009)
 
Webcon 2012 Mobile Development mit Sencha Touch
Webcon 2012  Mobile Development mit Sencha TouchWebcon 2012  Mobile Development mit Sencha Touch
Webcon 2012 Mobile Development mit Sencha Touch
 
PureSQL APEX Connect
PureSQL APEX ConnectPureSQL APEX Connect
PureSQL APEX Connect
 
Pure SQL for batch processing
Pure SQL for batch processingPure SQL for batch processing
Pure SQL for batch processing
 
TypeScript
TypeScriptTypeScript
TypeScript
 
Modern angular 02_angular_mit_type_script
Modern angular 02_angular_mit_type_scriptModern angular 02_angular_mit_type_script
Modern angular 02_angular_mit_type_script
 
Prototype 1.7
Prototype 1.7Prototype 1.7
Prototype 1.7
 
Funktionale Programmierung und mehr mit Scala
Funktionale Programmierung und mehr mit ScalaFunktionale Programmierung und mehr mit Scala
Funktionale Programmierung und mehr mit Scala
 

PostgreSQL: Eigene Aggregate schreiben

  • 1. Eigene Aggregatsfunktionen schreiben Hans-Jürgen Schönig www.postgresql-support.de Hans-Jürgen Schönig www.postgresql-support.de
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. Windowing und Analytics Hans-Jürgen Schönig www.postgresql-support.de
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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
  • 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. 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. 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. 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. 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. 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. 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. Finally . . . Hans-Jürgen Schönig www.postgresql-support.de
  • 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