Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.
The NoSQL Store everyoneThe NoSQL Store everyone
ignores: PostgreSQLignores: PostgreSQL
Stephan Hochdörfer // 04-06-2015
About meAbout me
Stephan Hochdörfer
Head of Technology, bitExpert AG
(Mannheim, Germany)
S.Hochdoerfer@bitExpert.de
@shoch...
End of relational databases?End of relational databases?
Freedom of NoSQL?Freedom of NoSQL?
NoSQL DatabasesNoSQL Databases
NoSQL Database TypesNoSQL Database Types
Graph Database
Object Database
Column Store
Key-Value Store
Document Store
Schemaless?Schemaless?
Schema changes
can be expensive
Can speed up
Development
Can help with
Continuous Delivery
Schemale...
PostgreSQL as the "glue"PostgreSQL as the "glue"
Peaceful coexistence...Peaceful coexistence...
Store documents in a
document-oriented fashion
Store relational data
in a r...
...but choose wisely...but choose wisely
Postgres DatatypesPostgres Datatypes
"Schemaless" datatypes:
Array
hstore
JSON / JSONb
XML
ArrayArray
« [...] PostgreSQL allows columns of a table to be
defined as variable-length multidimensional arrays. »
- Post...
Create array columnCreate array column
CREATE TABLE blogposts (
title text,
content text,
tags text[]
);
Multidimensional array FTW!Multidimensional array FTW!
CREATE TABLE tictactoe (
squares integer[3][3]
);
Insert arrayInsert array
INSERT INTO blogposts VALUES (
'Mein Blogpost',
'Lorem ipsum...',
ARRAY['lorem', 'ipsum', 'blogpo...
Insert arrayInsert array
INSERT INTO blogposts VALUES (
'Mein Blogpost',
'Lorem ipsum...',
'{"lorem", "ipsum", "blogpost"}...
Accessing array elementsAccessing array elements
SELECT tags[3] FROM blogposts;
tags
----------
blogpost
(2 rows)
Filtering arraysFiltering arrays
SELECT * from blogposts WHERE tags[2] = 'ipsum';
title | content | tags
-----------------...
Filtering arraysFiltering arrays
SELECT * FROM blogposts WHERE 'blogpost' = ANY(tags);
title | content | tags
------------...
Filtering arraysFiltering arrays
SELECT * FROM blogposts WHERE tags && ARRAY['lorem', 'blogpost'];
title | content | tags
...
Filtering arraysFiltering arrays
SELECT * FROM blogposts WHERE tags @> ARRAY['lorem', 'blogpost']
title | content | tags
-...
Generating a tag cloudGenerating a tag cloud
SELECT UNNEST(tags) as tag, COUNT(*) as cnt FROM blogposts
GROUP BY tag;
tag ...
Dealing with indexesDealing with indexes
CREATE INDEX tags_idx on "blogposts" USING GIN ("tags");
SET enable_seqscan TO of...
Updating arraysUpdating arrays
UPDATE blogposts SET tags = ARRAY['tag1', 'tag2', 'blogpost']
WHERE title = 'Mein Blogpost'...
Updating single array itemUpdating single array item
UPDATE blogposts SET tags[3] = 'tag3' WHERE title = 'Mein Blogpost';
...
Updating single array itemUpdating single array item
UPDATE blogposts SET tags[5] = 'tag6' WHERE title = 'Mein Blogpost';
...
Partial array updatePartial array update
UPDATE blogposts SET tags[4:5] = ARRAY['tag4', 'tag5']
WHERE title = 'Mein Blogpo...
Array functionsArray functions
array_dims()
array_upper()
array_lower()
array_length()
array_prepend()
array_append()
...
hstorehstore
« [...] data type for storing sets of key/value pairs within a single
PostgreSQL value. [...] Keys and values...
Install hstore extensionInstall hstore extension
CREATE EXTENSION hstore;
Create hstore columnCreate hstore column
CREATE TABLE products (
name text,
price float,
description text,
metadata hstore...
Insert hstore datasetInsert hstore dataset
INSERT INTO products VALUES (
'Product A',
123.3,
'Lorem ipsum',
'color => blac...
Filtering hstore datasetFiltering hstore dataset
SELECT metadata->'color' FROM products;
?column?
----------
black
red
(2 ...
Filtering hstore datasetFiltering hstore dataset
SELECT metadata->'weight' FROM products;
?column?
----------
3kg
(2 rows)
Search for a key in hstoreSearch for a key in hstore
SELECT * FROM products WHERE metadata ? 'weight';
name | price | desc...
Search for key/value in hstoreSearch for key/value in hstore
SELECT * FROM products WHERE metadata @> 'color => red';
name...
Query for all hstore keysQuery for all hstore keys
SELECT DISTINCT UNNEST(AKEYS(metadata)) as keys FROM products;
keys
---...
Dealing with indexesDealing with indexes
CREATE INDEX metadata_idx ON products USING GIN (metadata);
EXPLAIN ANALYZE SELEC...
Updating hstore datasetUpdating hstore dataset
UPDATE products SET metadata = 'color => black, weight => 5kg'::hstore WHER...
Partial hstore dataset updatePartial hstore dataset update
UPDATE products SET metadata = metadata || 'weight => 1kg'::hst...
Removing item from hstoreRemoving item from hstore
UPDATE products SET metadata = metadata - 'weight'::text;
hstore functionshstore functions
akeys()
avals()
hstore_to_array()
hstore_to_json()
...
hstore Example: Auditinghstore Example: Auditing
CREATE TABLE audit
(
change_date timestamptz default now(),
before hstore...
hstore Example: Auditinghstore Example: Auditing
create trigger audit
after update on example
for each row
execute procedu...
JSONJSON
« [...] the json data type has the advantage of checking
that each stored value is a valid JSON value. »
- Postgr...
Create JSON columnCreate JSON column
CREATE TABLE products (
name text,
price float,
description text,
metadata json
);
Insert JSON documentInsert JSON document
INSERT INTO products VALUES (
'Product A',
123.3,
'Lorem ipsum',
' { "color": "bl...
Insert JSON documentInsert JSON document
INSERT INTO products VALUES (
'Product C',
9.95,
'Lorem ipsum',
' { "color": ["re...
Insert JSON documentInsert JSON document
INSERT INTO products VALUES (
'Product D',
9.95,
'Lorem ipsum',
' { "color": ["re...
Filtering JSON documentFiltering JSON document
SELECT metadata->>'color' FROM products;
?column?
-------------------------...
Filtering JSON documentFiltering JSON document
SELECT metadata#>'{color, 2}' FROM products;
?column?
----------
"blue"
(3 ...
Dealing with indexesDealing with indexes
CREATE UNIQUE INDEX product_color ON products((metadata->>'color'));
INSERT INTO ...
Updating JSON documentUpdating JSON document
UPDATE products SET metadata = ' { "color": ["red", "green", "blue", "yellow"...
JSON functionsJSON functions
array_to_json()
row_to_json()
json_array_length()
json_object_keys()
...
Micro-JSON WebserviceMicro-JSON Webservice
SELECT row_to_json(products) FROM products WHERE name = 'Product C';
row_to_jso...
Micro-JSON WebserviceMicro-JSON Webservice
SELECT row_to_json(t)
FROM (
SELECT name, price FROM products WHERE name = 'Pro...
JSONbJSONb
« There are two JSON data types: json and jsonb [...]
The major practical difference is one of efficiency. »
- ...
Create JSONb columnCreate JSONb column
CREATE TABLE products (
name text,
price float,
description text,
metadata jsonb
);
Insert JSON documentInsert JSON document
INSERT INTO products VALUES (
'Product A',
123.3,
'Lorem ipsum',
' { "color": "bl...
Insert JSON documentInsert JSON document
INSERT INTO products VALUES (
'Product D',
9.95,
'Lorem ipsum',
' { "color": ["re...
Dealing with indexesDealing with indexes
CREATE INDEX metadata_idx ON products USING gin (metadata);
Search for key/value in JSONSearch for key/value in JSON
SELECT * FROM products WHERE metadata @> '{"color": "black"}';
na...
Search for key/value in JSONSearch for key/value in JSON
EXPLAIN ANALYZE SELECT * FROM products WHERE metadata @> '{"color...
JSON key lookupJSON key lookup
SELECT * FROM products WHERE metadata ? 'weight';
name | price | description | metadata
---...
JSON key lookupJSON key lookup
SELECT * FROM products WHERE metadata ?| array['weight', 'color'];
name | price | descripti...
JSON keys lookupJSON keys lookup
SELECT * FROM products WHERE metadata ?& array['weight', 'color'];
name | price | descrip...
JSON vs. JSONbJSON vs. JSONb
Use JSONb for complex
operations
JSONb needs more
disk space than JSON
Use JSON just for stor...
XMLXML
« [...] it checks the input values for well-formedness, and there
are support functions to perform type-safe operat...
Create XML columnCreate XML column
CREATE TABLE imports (
importDate date,
content XML
);
Insert XML documentInsert XML document
INSERT INTO imports VALUES (
'2014-04-05',
'<?xml version="1.0"?>
<order customer="...
Insert XML documentInsert XML document
INSERT INTO imports VALUES (
'2014-04-05',
'<?xml version="1.0"?>
<open></close>'::...
Filtering XML documentFiltering XML document
SELECT xpath('/order/product/@id', content) FROM imports;
xpath
-------------...
Filtering XML documentFiltering XML document
SELECT UNNEST(xpath('/order/product/@id', content)::text[])
as productid, COU...
Search in XML documentSearch in XML document
SELECT * FROM imports WHERE xpath_exists('/order/product[@id=9876]', content)...
Create XML documentCreate XML document
SELECT query_to_xml('SELECT * FROM products', true, false, '') as product;
product
...
XML functionsXML functions
xmlconcat()
xmlforest()
xmlagg()
xml_is_well_formed()
query_to_xml()
xpath()
...
Partition database tablesPartition database tables
« [...] Partitioning refers to splitting what is logically
one large ta...
Partition database tablesPartition database tables
CREATE TABLE sales_stats (
year int,
product text,
sales_by_quarter hst...
Partition database tablesPartition database tables
CREATE OR REPLACE FUNCTION sales_stats_part()
RETURNS TRIGGER AS
$BODY$...
Partition database tablesPartition database tables
IF NOT FOUND THEN
EXECUTE 'CREATE TABLE ' || quote_ident(_tablename) ||...
To infinity and beyond!To infinity and beyond!
Foreign Data Wrappers
Range datatype
Materialized views
Conditional Indexes...
Large ecosystemLarge ecosystem
PostgreSQL usersPostgreSQL users
Thank you!
Nächste SlideShare
Wird geladen in …5
×

Stefan Hochdörfer - The NoSQL Store everyone ignores: PostgreSQL - NoSQL matters Dublin 2015

925 Aufrufe

Veröffentlicht am

PostgreSQL is well known being an object-relational database management system. In it`s core PostgreSQL is schema-aware dealing with fixed database tables and column types. However, recent versions of PostgreSQL made it possible to deal with schema-free data. Learn which new features PostgreSQL supports and how to use those features in your application.

Veröffentlicht in: Daten & Analysen
  • Als Erste(r) kommentieren

Stefan Hochdörfer - The NoSQL Store everyone ignores: PostgreSQL - NoSQL matters Dublin 2015

  1. 1. The NoSQL Store everyoneThe NoSQL Store everyone ignores: PostgreSQLignores: PostgreSQL Stephan Hochdörfer // 04-06-2015
  2. 2. About meAbout me Stephan Hochdörfer Head of Technology, bitExpert AG (Mannheim, Germany) S.Hochdoerfer@bitExpert.de @shochdoerfer #PHP, #DevOps, #Automation, #unKonf
  3. 3. End of relational databases?End of relational databases?
  4. 4. Freedom of NoSQL?Freedom of NoSQL?
  5. 5. NoSQL DatabasesNoSQL Databases
  6. 6. NoSQL Database TypesNoSQL Database Types Graph Database Object Database Column Store Key-Value Store Document Store
  7. 7. Schemaless?Schemaless? Schema changes can be expensive Can speed up Development Can help with Continuous Delivery Schemaless does not mean unstructured!
  8. 8. PostgreSQL as the "glue"PostgreSQL as the "glue"
  9. 9. Peaceful coexistence...Peaceful coexistence... Store documents in a document-oriented fashion Store relational data in a relational schema
  10. 10. ...but choose wisely...but choose wisely
  11. 11. Postgres DatatypesPostgres Datatypes "Schemaless" datatypes: Array hstore JSON / JSONb XML
  12. 12. ArrayArray « [...] PostgreSQL allows columns of a table to be defined as variable-length multidimensional arrays. » - PostgreSQL documentation
  13. 13. Create array columnCreate array column CREATE TABLE blogposts ( title text, content text, tags text[] );
  14. 14. Multidimensional array FTW!Multidimensional array FTW! CREATE TABLE tictactoe ( squares integer[3][3] );
  15. 15. Insert arrayInsert array INSERT INTO blogposts VALUES ( 'Mein Blogpost', 'Lorem ipsum...', ARRAY['lorem', 'ipsum', 'blogpost'] ); INSERT INTO blogposts VALUES ( 'Mein zweiter Blogpost', 'Lorem ipsum...', ARRAY['lorem', 'ipsum'] );
  16. 16. Insert arrayInsert array INSERT INTO blogposts VALUES ( 'Mein Blogpost', 'Lorem ipsum...', '{"lorem", "ipsum", "blogpost"}' ); INSERT INTO blogposts VALUES ( 'Mein zweiter Blogpost', 'Lorem ipsum...', '{"lorem", "ipsum"}' );
  17. 17. Accessing array elementsAccessing array elements SELECT tags[3] FROM blogposts; tags ---------- blogpost (2 rows)
  18. 18. Filtering arraysFiltering arrays SELECT * from blogposts WHERE tags[2] = 'ipsum'; title | content | tags -----------------------+----------------+------------------------ Mein Blogpost | Lorem ipsum... | {lorem,ipsum,blogpost} Mein zweiter Blogpost | Lorem ipsum... | {lorem,ipsum} (2 rows)
  19. 19. Filtering arraysFiltering arrays SELECT * FROM blogposts WHERE 'blogpost' = ANY(tags); title | content | tags ---------------+----------------+------------------------ Mein Blogpost | Lorem ipsum... | {lorem,ipsum,blogpost} (1 row)
  20. 20. Filtering arraysFiltering arrays SELECT * FROM blogposts WHERE tags && ARRAY['lorem', 'blogpost']; title | content | tags -----------------------+----------------+------------------------ Mein Blogpost | Lorem ipsum... | {lorem,ipsum,blogpost} Mein zweiter Blogpost | Lorem ipsum... | {lorem,ipsum} (2 rows)
  21. 21. Filtering arraysFiltering arrays SELECT * FROM blogposts WHERE tags @> ARRAY['lorem', 'blogpost'] title | content | tags ---------------+----------------+------------------------ Mein Blogpost | Lorem ipsum... | {lorem,ipsum,blogpost} (1 row)
  22. 22. Generating a tag cloudGenerating a tag cloud SELECT UNNEST(tags) as tag, COUNT(*) as cnt FROM blogposts GROUP BY tag; tag | cnt ----------+----- blogpost | 1 lorem | 2 ipsum | 2 (3 rows)
  23. 23. Dealing with indexesDealing with indexes CREATE INDEX tags_idx on "blogposts" USING GIN ("tags"); SET enable_seqscan TO off; EXPLAIN ANALYZE SELECT * FROM blogposts WHERE tags @> ARRAY['tag3']; QUERY PLAN -------------------------------------------------------------------- Bitmap Heap Scan on blogposts (cost=8.00..12.01 rows=1 width=96) (actual time=0.0 Recheck Cond: (tags @> '{tag3}'::text[]) -> Bitmap Index Scan on tags_idx (cost=0.00..8.00 rows=1 width=0) (actual time Index Cond: (tags @> '{tag3}'::text[]) Total runtime: 0.131 ms (5 rows)
  24. 24. Updating arraysUpdating arrays UPDATE blogposts SET tags = ARRAY['tag1', 'tag2', 'blogpost'] WHERE title = 'Mein Blogpost'; SELECT * FROM blogposts; title | content | tags -----------------------+----------------+---------------------- Mein zweiter Blogpost | Lorem ipsum... | {lorem,ipsum} Mein Blogpost | Lorem ipsum... | {tag1,tag2,blogpost} (2 rows)
  25. 25. Updating single array itemUpdating single array item UPDATE blogposts SET tags[3] = 'tag3' WHERE title = 'Mein Blogpost'; SELECT * FROM blogposts; title | content | tags -----------------------+----------------+------------------ Mein zweiter Blogpost | Lorem ipsum... | {lorem,ipsum} Mein Blogpost | Lorem ipsum... | {tag1,tag2,tag3} (2 rows)
  26. 26. Updating single array itemUpdating single array item UPDATE blogposts SET tags[5] = 'tag6' WHERE title = 'Mein Blogpost'; SELECT * FROM blogposts; title | content | tags -----------------------+----------------+---------------------------- Mein zweiter Blogpost | Lorem ipsum... | {lorem,ipsum} Mein Blogpost | Lorem ipsum... | {tag1,tag2,tag3,NULL,tag6} (2 rows)
  27. 27. Partial array updatePartial array update UPDATE blogposts SET tags[4:5] = ARRAY['tag4', 'tag5'] WHERE title = 'Mein Blogpost'; title | content | tags -----------------------+----------------+---------------------------- Mein zweiter Blogpost | Lorem ipsum... | {lorem,ipsum} Mein Blogpost | Lorem ipsum... | {tag1,tag2,tag3,tag4,tag5} (2 rows)
  28. 28. Array functionsArray functions array_dims() array_upper() array_lower() array_length() array_prepend() array_append() ...
  29. 29. hstorehstore « [...] data type for storing sets of key/value pairs within a single PostgreSQL value. [...] Keys and values are simply text strings. » - PostgreSQL documentation
  30. 30. Install hstore extensionInstall hstore extension CREATE EXTENSION hstore;
  31. 31. Create hstore columnCreate hstore column CREATE TABLE products ( name text, price float, description text, metadata hstore );
  32. 32. Insert hstore datasetInsert hstore dataset 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 );
  33. 33. Filtering hstore datasetFiltering hstore dataset SELECT metadata->'color' FROM products; ?column? ---------- black red (2 rows)
  34. 34. Filtering hstore datasetFiltering hstore dataset SELECT metadata->'weight' FROM products; ?column? ---------- 3kg (2 rows)
  35. 35. Search for a key in hstoreSearch for a key in hstore SELECT * FROM products WHERE metadata ? 'weight'; name | price | description | metadata -----------+-------+-------------+----------------------------------- Product A | 123.3 | Lorem ipsum | "color"=>"black", "weight"=>"3kg" (1 row)
  36. 36. Search for key/value in hstoreSearch for key/value in hstore SELECT * FROM products WHERE metadata @> 'color => red'; name | price | description | metadata -----------+-------+-------------+---------------- Product B | 45 | Lorem ipsum | "color"=>"red" (1 row)
  37. 37. Query for all hstore keysQuery for all hstore keys SELECT DISTINCT UNNEST(AKEYS(metadata)) as keys FROM products; keys -------- weight color (2 rows)
  38. 38. Dealing with indexesDealing with indexes CREATE INDEX metadata_idx ON products USING GIN (metadata); EXPLAIN ANALYZE SELECT * FROM products WHERE metadata @> 'color => red'; QUERY PLAN --------------------------------------------------------------------- Bitmap Heap Scan on products (cost=12.00..16.01 rows=1 width=104) (actual time=0. Recheck Cond: (metadata @> '"color"=>"red"'::hstore) -> Bitmap Index Scan on metadata_idx (cost=0.00..12.00 rows=1 width=0) (actual Index Cond: (metadata @> '"color"=>"red"'::hstore) Total runtime: 0.100 ms (5 rows)
  39. 39. Updating hstore datasetUpdating hstore dataset UPDATE products SET metadata = 'color => black, weight => 5kg'::hstore WHERE name =
  40. 40. Partial hstore dataset updatePartial hstore dataset update UPDATE products SET metadata = metadata || 'weight => 1kg'::hstore WHERE name = 'Pr
  41. 41. Removing item from hstoreRemoving item from hstore UPDATE products SET metadata = metadata - 'weight'::text;
  42. 42. hstore functionshstore functions akeys() avals() hstore_to_array() hstore_to_json() ...
  43. 43. hstore Example: Auditinghstore Example: Auditing CREATE TABLE audit ( change_date timestamptz default now(), before hstore, after hstore ); create function audit() returns trigger language plpgsql as $$ begin INSERT INTO audit(before, after) SELECT hstore(old), hstore(new); return new; end; $$;
  44. 44. hstore Example: Auditinghstore Example: Auditing create trigger audit after update on example for each row execute procedure audit(); select change_date, after - before as diff from audit; change_date | diff -------------------------------+----------- 2013-11-08 09:29:19.808217+02 | "f1"=>"b" 2013-11-08 09:29:19.808217+02 | "f2"=>"c" (2 rows) Source: Auditing Changes with Hstore
  45. 45. JSONJSON « [...] the json data type has the advantage of checking that each stored value is a valid JSON value. » - PostgreSQL documentation
  46. 46. Create JSON columnCreate JSON column CREATE TABLE products ( name text, price float, description text, metadata json );
  47. 47. Insert JSON documentInsert JSON document 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" } ' );
  48. 48. Insert JSON documentInsert JSON document INSERT INTO products VALUES ( 'Product C', 9.95, 'Lorem ipsum', ' { "color": ["red", "green", "blue"] } ' );
  49. 49. Insert JSON documentInsert JSON document INSERT INTO products VALUES ( 'Product D', 9.95, 'Lorem ipsum', ' { "color": ["red", "green", "blue", ] } ' ); ERROR: invalid input syntax for type json LINE 5: ' { "color": ["red", "green", "blue", ] } ' ^ DETAIL: Expected JSON value, but found "]". CONTEXT: JSON data, line 1: { "color": ["red", "green", "blue", ]...
  50. 50. Filtering JSON documentFiltering JSON document SELECT metadata->>'color' FROM products; ?column? -------------------------- black red ["red", "green", "blue"] (3 rows)
  51. 51. Filtering JSON documentFiltering JSON document SELECT metadata#>'{color, 2}' FROM products; ?column? ---------- "blue" (3 rows)
  52. 52. Dealing with indexesDealing with indexes 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.
  53. 53. Updating JSON documentUpdating JSON document UPDATE products SET metadata = ' { "color": ["red", "green", "blue", "yellow"] } '
  54. 54. JSON functionsJSON functions array_to_json() row_to_json() json_array_length() json_object_keys() ...
  55. 55. Micro-JSON WebserviceMicro-JSON Webservice SELECT row_to_json(products) FROM products WHERE name = 'Product C'; row_to_json --------------------------------------------------------------------- {"name":"Product C","price":9.95,"description":"Lorem ipsum","metadata": { "color" (1 row)
  56. 56. Micro-JSON WebserviceMicro-JSON Webservice SELECT row_to_json(t) FROM ( SELECT name, price FROM products WHERE name = 'Product C' ) t; row_to_json ----------------------------------- {"name":"Product C","price":9.95} (1 row)
  57. 57. JSONbJSONb « There are two JSON data types: json and jsonb [...] The major practical difference is one of efficiency. » - PostgreSQL documentation
  58. 58. Create JSONb columnCreate JSONb column CREATE TABLE products ( name text, price float, description text, metadata jsonb );
  59. 59. Insert JSON documentInsert JSON document 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" } ' );
  60. 60. Insert JSON documentInsert JSON document INSERT INTO products VALUES ( 'Product D', 9.95, 'Lorem ipsum', ' { "color": ["red", "green", "blue", ] } ' ); ERROR: invalid input syntax for type json LINE 5: ' { "color": ["red", "green", "blue", ] } ' ^ DETAIL: Expected JSON value, but found "]". CONTEXT: JSON data, line 1: { "color": ["red", "green", "blue", ]...
  61. 61. Dealing with indexesDealing with indexes CREATE INDEX metadata_idx ON products USING gin (metadata);
  62. 62. Search for key/value in JSONSearch for key/value in JSON SELECT * FROM products WHERE metadata @> '{"color": "black"}'; name | price | description | metadata ------------+---------+-----------------+---------------------------- Product A | 123.3 | Lorem ipsum | {"color": "black", "weight": "3kg"} (1 row)
  63. 63. Search for key/value in JSONSearch for key/value in JSON EXPLAIN ANALYZE SELECT * FROM products WHERE metadata @> '{"color": "black"}'; QUERY PLAN -------------------------------------------------------------------- Bitmap Heap Scan on products (cost=12.00..16.01 rows=1 width=104) (actual time=0. Recheck Cond: (metadata @> '{"color": "black"}'::jsonb) Heap Blocks: exact=1 -> Bitmap Index Scan on metadata_idx (cost=0.00..12.00 rows=1 width=0) (actual Index Cond: (metadata @> '{"color": "black"}'::jsonb) Planning time: 0.131 ms Execution time: 0.105 ms
  64. 64. JSON key lookupJSON key lookup SELECT * FROM products WHERE metadata ? 'weight'; name | price | description | metadata ------------+---------+-----------------+---------------------------- Product A | 123.3 | Lorem ipsum | {"color": "black", "weight": "3kg"} (1 row)
  65. 65. JSON key lookupJSON key lookup SELECT * FROM products WHERE metadata ?| array['weight', 'color']; name | price | description | metadata ------------+---------+-----------------+---------------------------- Product A | 123.3 | Lorem ipsum | {"color": "black", "weight": "3kg"} Product B | 45 | Lorem ipsum | {"color": "red"}
  66. 66. JSON keys lookupJSON keys lookup SELECT * FROM products WHERE metadata ?& array['weight', 'color']; name | price | description | metadata ------------+---------+-----------------+---------------------------- Product A | 123.3 | Lorem ipsum | {"color": "black", "weight": "3kg"} (1 row)
  67. 67. JSON vs. JSONbJSON vs. JSONb Use JSONb for complex operations JSONb needs more disk space than JSON Use JSON just for storage Use JSON when you need to keep the structure
  68. 68. XMLXML « [...] it checks the input values for well-formedness, and there are support functions to perform type-safe operations on it. » - PostgreSQL documentation
  69. 69. Create XML columnCreate XML column CREATE TABLE imports ( importDate date, content XML );
  70. 70. Insert XML documentInsert XML document INSERT INTO imports VALUES ( '2014-04-05', '<?xml version="1.0"?> <order customer="4711"> <product id="1234">10</product> <product id="9876">50</product> </order>'::xml ); INSERT INTO imports VALUES ( '2014-04-05', '<?xml version="1.0"?> <order customer="5432"> <product id="1234">3</product> </order>'::xml );
  71. 71. Insert XML documentInsert XML document INSERT INTO imports VALUES ( '2014-04-05', '<?xml version="1.0"?> <open></close>'::xml ); ERROR: invalid XML content LINE 3: '<?xml version="1.0"?> ^ DETAIL: line 2: Opening and ending tag mismatch: open line 2 and close <open></close> ^ line 2: chunk is not well balanced <open></close> ^
  72. 72. Filtering XML documentFiltering XML document SELECT xpath('/order/product/@id', content) FROM imports; xpath ------------- {1234,9876} {1234} (2 rows)
  73. 73. Filtering XML documentFiltering XML document SELECT UNNEST(xpath('/order/product/@id', content)::text[]) as productid, COUNT(*) as orders FROM imports GROUP BY productid; productid | orders -----------+-------- 9876 | 1 1234 | 2 (2 rows)
  74. 74. Search in XML documentSearch in XML document SELECT * FROM imports WHERE xpath_exists('/order/product[@id=9876]', content); importdate | content ------------+--------------------------------- 2014-04-05 | <order customer="4711"> + | <product id="1234">10</product>+ | <product id="9876">50</product>+ | </order> (1 row)
  75. 75. Create XML documentCreate XML document SELECT query_to_xml('SELECT * FROM products', true, false, '') as product; product -------------------------------------------------------------------- <table xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + + <row> + <name>Product A</name> + <price>123.3</price> + <description>Lorem ipsum</description> + <metadata> { "color": "black", "weight": "3kg" } </metadata> + </row> + + </table> + (1 row)
  76. 76. XML functionsXML functions xmlconcat() xmlforest() xmlagg() xml_is_well_formed() query_to_xml() xpath() ...
  77. 77. Partition database tablesPartition database tables « [...] Partitioning refers to splitting what is logically one large table into smaller physical pieces. » - PostgreSQL documentation
  78. 78. Partition database tablesPartition database tables CREATE TABLE sales_stats ( year int, product text, sales_by_quarter hstore ); CREATE TABLE sales_stats_2012( CHECK ( year = 2012 ) ) INHERITS (sales_stats); CREATE TABLE sales_stats_2011( CHECK ( year = 2011 ) ) INHERITS (sales_stats);
  79. 79. Partition database tablesPartition database tables CREATE OR REPLACE FUNCTION sales_stats_part() RETURNS TRIGGER AS $BODY$ DECLARE _new_time int; _tablename text; _year text; _result record; BEGIN _new_time := ((NEW."time"/86400)::int)*86400; _year := to_char(to_timestamp(_new_time), 'YYYY'); _tablename := 'sales_stats_'||_year; PERFORM 1 FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind = 'r' AND c.relname = _tablename;
  80. 80. Partition database tablesPartition database tables IF NOT FOUND THEN EXECUTE 'CREATE TABLE ' || quote_ident(_tablename) || ' ( CHECK ( year = ' || quote_literal(_year) || ')) ) INHERITS (sales_stats)'; END IF; EXECUTE 'INSERT INTO ' || quote_ident(_tablename) || ' VALUES ($1.*)' USING NEW; RETURN NULL; END; $BODY$ LANGUAGE plpgsql; CREATE TRIGGER sales_stats_trigger BEFORE INSERT ON sales_stats FOR EACH ROW EXECUTE PROCEDURE sales_stats_part();
  81. 81. To infinity and beyond!To infinity and beyond! Foreign Data Wrappers Range datatype Materialized views Conditional Indexes ...
  82. 82. Large ecosystemLarge ecosystem
  83. 83. PostgreSQL usersPostgreSQL users
  84. 84. Thank you!

×