PostgreSQL: Die NoSQL Datenbank
Stephan Hochdörfer // 10.02.2014
PostgreSQL: Die NoSQL Datenbank die niemand kennt
Über mich
Stephan Hochdörfer
Head of IT , bitExpert AG (Mannheim)
S.Hochdoerfer@bitExpert.de
@shochdoerfer
#PHP, #DevOps, #Automation
Ende des relationalen Wegs?
Sind relationale Datenbanken immer noch der richtige Weg?
Sind unsere Daten wirklich relational?
"Freiheit" durch NoSQL?
Entwickler müssen nicht mehr in festgelegten Strukturen denken
Agiles Vorgehen, sich einfach den ständig ändernden Kundenanforderungen unterwerfen
Datenspeicher "limitiert" uns nicht mehr...
Friedliche Co-Existenz...
Speichere relationale Daten relational
Speichere Dokumente dokumentenorientiert
...aber richtig entscheiden!
Sarah Mei (Diaspora): Why You Should Never Use MongoDB
PostgreSQL als Bindeglied
Postgres kann beide Welten vereinen. Über 300 verschd. Datentypen ermöglichen es eine Vielzahl von unterschiedlichen Informationen zu speichern.
Normalisierung ist kein Muss, hilft aber Daten zu organisieren. Pragmatisch sein!
Postgres Datentypen
"Schemafreie" Datentypen:
hstore Support seit 2003
JSON Support seit 2006, seit 9.2 im Core
NoSQL Bewegung entstand "erst" in 2009. Es war also schon lange Zeit vorher möglich "Dokumente" in PostgreSQL zu speichern
Array
« [...] PostgreSQL allows columns of a table to be defined as variable-length multidimensional arrays. » - PostgreSQL documentation
Arrays of any built-in or user-defined base type, enum type, or composite type can be created.
Anwendungsfall: Einsparen von 1:n Tabellen (z.B. Tags bei Blogpost)
Array Spalte anlegen
CREATE TABLE blogposts (
title text ,
content text ,
tags text []
);
Daten als Array speichern
INSERT INTO blogposts VALUES (
'Mein Blogpost' ,
'Lorem ipsum...' ,
ARRAY [ 'lorem' , 'ipsum' , 'blogpost' ]
);
INSERT INTO blogposts VALUES (
'Mein zweiter Blogpost' ,
'Lorem ipsum...' ,
ARRAY [ 'lorem' , 'ipsum' ]
);
Array Elemente abfragen
SELECT tags[ 3 ] FROM blogposts;
tags
----------
blogpost
( 2 rows )
Arrays durchsuchen
SELECT * FROM blogposts WHERE 'blogpost' = ANY ( tags);
title | content | tags
---------------+----------------+------------------------
Mein Blogpost | Lorem ipsum... | { lorem, ipsum, blogpost}
( 1 row )
Wenn es ANY gibt dann gibt es natürlich auch ALL. Macht in diesem Anwendungsfall allerdings wenig Sinn...
Kann zu Performanceproblemen führen wenn die Arrays viele Einträge haben
hstore
« [...] data type for storing sets of key/value pairs within a single PostgreSQL value. [...] Keys and values are simply text strings. » - PostgreSQL documentation
Unstrukturierte Daten; Hash-Map; Key muss eindeutig sein, es gibt keine Regel wenn Keys mehrfach übergeben welcher Key "gewinnt"
hstore Extension installieren
CREATE EXTENSION hstore;
Nicht Teil des PostgreSQL Cores, muss separat "installiert" und eingebunden werden. (postgres-contrib)
hstore Spalte anlegen
CREATE TABLE products (
name text ,
price float ,
description text ,
metadata hstore
);
hstore Daten speichern
INSERT INTO products VALUES (
'Product A' ,
123.3 ,
'Lorem ipsum' ,
'color => black, weight => 3kg' : :hstore
);
INSERT INTO products VALUES (
'Product B' ,
45.0 ,
'Lorem ipsum' ,
'color => red' : :hstore
);
hstore Keys abfragen
SELECT metadata-> 'color' FROM products;
?column ?
----------
black
red
( 2 rows )
hstore Keys suchen
SELECT name FROM products WHERE metadata ? 'weight' ;
name
-----------
Product A
( 1 row )
hstore Key/Value suchen
SELECT name FROM products WHERE metadata @> 'color => black' ;
name
-----------
Product A
( 1 row )
JSON
« [...] the json data type has the advantage of checking that each stored value is a valid JSON value. » - PostgreSQL documentation
Speichert JSON (JavaScript Object Notation) Daten gemäß RFC 4627
JSON Spalte anlegen
CREATE TABLE products (
name text ,
price float ,
description text ,
metadata json
);
JSON Daten speichern
INSERT INTO products VALUES (
'Product A' ,
123.3 ,
'Lorem ipsum' ,
' { "color": "black", "weight": "3kg" } '
);
INSERT INTO products VALUES (
'Product B' ,
45.0 ,
'Lorem ipsum' ,
' { "color": "red" } '
);
JSON Daten speichern
INSERT INTO products VALUES (
'Product C' ,
9.95 ,
'Lorem ipsum' ,
' { "color": ["red", "green", "blue"] } '
);
JSON Daten abfragen
SELECT metadata->> 'color' FROM products;
?column ?
--------------------------
black
red
[ "red" , "green" , "blue" ]
( 3 rows )
JSON Inhalte indexieren
CREATE UNIQUE INDEX product_color ON products (( metadata->> 'color' ));
INSERT INTO products VALUES (
'Product D' ,
21.95 ,
'Lorem ipsum' ,
' { "color": "red" } '
);
ERROR: duplicate key value violates unique constraint "product_color"
DETAIL: Key (( metadata ->> 'color' : :text ))=( red) already exists .
XML
« [...] it checks the input values for well-formedness, and there are support functions to perform type-safe operations on it. » - PostgreSQL documentation
Überprüft wohlgeformte Dokumente, kein DTD oder XMLSchema Check!
XML Spalte anlegen
CREATE TABLE imports (
importDate date ,
content XML
);
XML Daten speichern
INSERT INTO imports VALUES (
'2014-02-10' ,
'<?xml version="1.0"?>
<order customer="4711">
<product id="1234">10</product>
<product id="9876">50</product>
</order>' : :xml
);
XML Daten abfragen
SELECT xpath ( '/order/product/@id' , content ) FROM imports;
xpath
-------------
{ 1234 , 9876 }
( 1 row )
...und darüber hinaus
Foreign Data Wrappers
Conditional Indexes
Range Datentyp
Materialized views
...
Vielen Dank für die Aufmerksamkeit!