SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our User Agreement and Privacy Policy.
SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our Privacy Policy and User Agreement for details.
Successfully reported this slideshow.
Activate your 14 day free trial to unlock unlimited reading.
1.
PostgreSQL 9.4 - Novinky (a JSONB)
Tomáš Vondra, GoodData (tomas.vondra@gooddata.com)
http://blog.pgaddict.com (tomas@pgaddict.com)
2.
9.4 release notes
http://www.postgresql.org/docs/9.4/static/release-9-4.html
článek od Pavla Stěhule (květen 2015)
http://www.root.cz/clanky/postgresql-9-4-transakcni-sql-json-databaze/
What's new in PostgreSQL 9.4 (Magnus Hagander)
http://www.hagander.net/talks/postgresql94_2.pdf
PostgreSQL Conference Europe 2014 (říjen, Madrid)
https://wiki.postgresql.org/wiki/PostgreSQL_Conference_Europe_Talks_2014
4.
Aktuální stav
● testuje se beta3
– Pomozte s testováním!
– Aplikační testy nade vše (zkuste svoji aplikaci na 9.4).
● trochu statistiky
– 2222 souborů změněno
– 131805 nových řádek (+)
– 59333 smazaných řádek (-)
● méně než 9.3 ...
– ale všichni víme že LOC je výborná metrika ;-)
6.
Takže co je vlastně nového?
● vývojářské / SQL vlastnosti
● DBA a administrace
● replikace a recovery
● infrastruktura
7.
Vývojářské / SQL vlastnosti
● agregační funkce
– FILTER aggregates
– ordered-set aggregates
– další menší vylepšení
● vylepšení aktualizovatelných pohledů
● UNNEST (WITH ORDINALITY)
● pl/pgsql stacktrace
● JSONB (nejlepší na závěr)
8.
agregační výrazy (FILTER)
SELECT
a,
SUM(CASE WHEN b < 10 THEN c ELSE NULL END) AS pod_10,
SUM(CASE WHEN b >= 10 THEN c ELSE NULL END) AS nad_10
FROM tabulka GROUP BY a;
SELECT
a,
SUM(c) FILTER (WHERE b < 10) AS pod_10,
SUM(c) FILTER (WHERE b >= 10) AS nad_10
FROM tabulka GROUP BY a;
9.
ordered-set aggregates
● pořadí vstupních hodnot není definováno
– často nepodstatné (MIN, MAX, SUM, …)
– někdy na něm ale záleží (array_agg, string_agg, …)
– lze ho určit pomocí ORDER BY ve volání funkce
SELECT
a,
SUM(b ORDER BY c) AS suma_b_serazene_dle_c,
ARRAY_AGG(b ORDER BY c) AS pole_b_serazene_dle_c
FROM tabulka GROUP BY a;
( Toto není ordered-set aggregate! )
10.
ordered-set aggregates
● některé agregační funkce pořadí vyžadují
– z definice (jinak to prostě nedává smysl)
– rank, percentil, ...
– direct / aggregate argumenty (rozdíl)
SELECT
a,
PERCENTILE_DISC(0.5)
WITHIN GROUP (ORDER BY b) AS median_b
FROM tabulka GROUP BY a;
11.
ordered-set aggregates
● některé agregační funkce pořadí vyžadují
– z definice (jinak to prostě nedává smysl)
– rank, percentil, ...
– direct / aggregate argumenty (rozdíl)
SELECT
a,
PERCENTILE_DISC(ARRAY[0.25, 0.5, 0.75])
WITHIN GROUP (ORDER BY b) AS median_b
FROM tabulka GROUP BY a;
( proprietární rozšíření )
12.
hypotetické agregační funkce
● Kam by se zařadila daná hodnota?
– pořadí – rank(..), dense_rank(..)
– relativní (0, 1) – percent_rank(..), cume_dist(..)
SELECT
a,
rank('xyz') WITHIN GROUP (ORDER BY b),
dense_rank('xyz') WITHIN GROUP (ORDER BY b),
percent_rank('xyz') WITHIN GROUP (ORDER BY b)
FROM tabulka GROUP BY a;
13.
agregační funkce / další vylepšení
● group keys v EXPLAIN
EXPLAIN SELECT COUNT(a) FROM tabulka GROUP BY b;
QUERY PLAN
--------------------------------------------------------------
HashAggregate (cost=195.00..195.11 rows=11 width=8)
Group Key: b
-> Seq Scan on tabulka (cost=0.00..145.00 rows=100 width=8)
(3 rows)
14.
automaticky updatovatelné pohledy
● pro jednoduché pohledy lze „překládat“ DML příkazy
– jedna tabulka ve FROM
– bez agregací / množinových operací, apod.
– pouze jednoduché odkazy na sloupce tabulky
– nesmí být označený pomocí „security_barrier“
● od 9.4 lze používat výrazy, konstanty, volání funkcí
– samozřejmě tyto sloupce nelze měnit
CREATE VIEW zamestnanci_view AS
SELECT emp_id, dept_id,
(salary*0.6) AS cista_mzda
FROM zamestnanci_tabulka
WHERE dept_id IN (10, 20);
15.
automaticky updatovatelné pohledy
● řádky odfiltrované přes WHERE nelze updatovat
● řádek ale může „vypadnout“
– WITH CHECK OPTION tomu zabrání
– další krok na cestě k „Row Level Security“ (řízení přístupu k
řádkům)
CREATE VIEW zamestnanci_view AS
SELECT id_zamestnance, id_oddeleni,
(plat*0.6) AS cista_mzda
FROM zamestnanci_tabulka
WHERE id_oddeleni IN (10, 20) WITH CHECK OPTION;
UPDATE zamestnanci_view SET id_oddeleni = 30;
16.
unnest
SELECT unnest(ARRAY[1,2,3]) AS a;
a
---
1
2
3
(3 rows)
17.
unnest
SELECT unnest(ARRAY[1,2,3]) AS a,
unnest(ARRAY[4,5,6]) AS b;
18.
unnest
SELECT unnest(ARRAY[1,2,3]) AS a,
unnest(ARRAY[4,5,6]) AS b;
a | b
---+---
1 | 4
2 | 5
3 | 6
(3 rows)
19.
unnest
SELECT unnest(ARRAY[1,2,3]) AS a,
unnest(ARRAY[4,5]) AS b;
20.
unnest
SELECT unnest(ARRAY[1,2,3]) AS a,
unnest(ARRAY[4,5]) AS b;
a | b
---+---
1 | 4
2 | 5
3 | 4
1 | 5
2 | 4
3 | 5
(6 rows)
21.
unnest
SELECT *
FROM unnest(ARRAY[1,2,3], ARRAY[4,5]) AS t(a,b);
a | b
---+---
1 | 4
2 | 5
3 |
(3 rows)
22.
unnest
SELECT *
FROM unnest(ARRAY[1,2,3], ARRAY[4,5])
WITH ORDINALITY AS t(a,b);
a | b | ordinality
---+---+------------
1 | 4 | 1
2 | 5 | 2
3 | | 3
(3 rows)
23.
unnest / ROWS FROM
SELECT a, b, ordinality
FROM ROWS FROM (unnest(ARRAY[1,2,3]),
unnest(ARRAY[4,5]))
WITH ORDINALITY AS t(a,b);
SELECT a, b, ordinality
FROM ROWS FROM (unnest(ARRAY[1,2,3]),
generate_series(1,10))
WITH ORDINALITY AS t(a,b);
24.
PL/pgSQL / call stack
CREATE OR REPLACE FUNCTION inner_func() RETURNS integer
AS $$
DECLARE
stack text;
BEGIN
GET DIAGNOSTICS stack = PG_CONTEXT;
RAISE NOTICE E'--- Call Stack ---n%', stack;
RETURN 1;
END;
$$ LANGUAGE plpgsql;
SELECT outer_func();
NOTICE: --- Call Stack ---
PL/pgSQL function inner_func() line 4 at GET DIAGNOSTICS
PL/pgSQL function outer_func() line 3 at RETURN
...
25.
PL/pgSQL / call stack
CREATE OR REPLACE FUNCTION inner_func() RETURNS integer
AS $$
DECLARE
stack text;
BEGIN
GET DIAGNOSTICS stack = PG_CONTEXT;
RAISE NOTICE E'--- Call Stack ---n%', stack;
RETURN 1;
EXCEPTION WHEN others THEN
GET STACKED DIAGNOSTICS stack = PG_ERROR_CONTEXT;
RAISE NOTICE E'--- Exception Call Stack ---n%',
stack;
END;
$$ LANGUAGE plpgsql;
(od 9.2, oboje Pavel Stěhule)
26.
DBA a administrace
● MATERIALIZED VIEWS
● přesun objektů mezi tablespacy
● vylepšení GIN (komprese, fast scan)
● ALTER SYSTEM / pg_reload_conf
● nové konfigurační parametry
● pg_prewarm
● pg_stat_statements (query ID)
27.
MATERIALIZED VIEWS
CREATE MATERIALIZED VIEW my_view AS SELECT …;
CREATE UNIQUE INDEX my_index ON my_view (…);
REFRESH MATERIALIED VIEW my_view;
REFRESH MATERIALIED VIEW CONCURRENTLY my_view;
28.
SET TABLESPACE ...
ALTER TABLE ALL IN TABLESPACE tablespace1
OWNED BY uzivatel
SET TABLESPACE tablespace2 [NOWAIT];
ALTER INDEX ...
ALTER VIEW ...
ALTER MATERIALIZED VIEW …
(rozdíl oproti Pavlově článku / Magnusově prezentaci)
29.
Vylepšení GIN indexů
● pro hodnoty složené z „částí“ (pole, slova, …)
● index se skládá z položek
key1 => [rowid1, rowid2, rowid3, …]
key2 => [rowid10, rowid20, rowid30, …]
…
● v podstatě bitmapové indexy (zvláštně kódované)
– jde použít na skalární typy (extenze btree_gin)
● dvě významná vylepšení v 9.4
– komprese posting listů (seznam odkazů na řádky)
– fast scan (dotazy typu „častý & vzácný“ výrazně rychlejší)
30.
ALTER SYSTEM
● dosud bylo nutné přímo editovat postgresql.conf
$ vim /var/lib/pgsql/9.1/data/postgresql.conf
● nově je možné toho dosáhnout přímo z databáze
ALTER SYSTEM SET work_mem = '128MB';
● vytvoří se nový soubor s konfigurací (include)
postgresql.auto.conf
● stále nutný explicitní reload / restart :-(
SELECT pg_reload_conf();
31.
Konfigurační parametry
● autovacuum_work_mem
– odděleno z maintenance_work_mem
● huge_pages
– Linuxové systémy s velkým objemem RAM
● session_preload_libraries
– načtení sdílených knihoven
– na rozdíl od local_preload_libraries libovolných
● wal_log_hints
– standardně se nelogují
– ale občas jsou užitečné - replikace, rewind
● (maintenance_)work_mem / effective_cache_size
– navýšení default hodnot (4x)
32.
pg_prewarm
● triviální způsob jak „zahřát cache“
– page cache (kernel) i shared buffers (DB)
– statistiky shared_buffers lze získat přes pg_buffercache
pg_prewarm(regclass,
mode text default 'buffer',
fork text default 'main',
first_block int8 default null,
last_block int8 default null)
RETURNS int8
(možná kombinace s pgfincore)
33.
pg_stat_statements
● texty dotazů se ukládají do souboru
– šetří sdílenou paměť
– odstraňuje limit na délku dotazu
● doplnění „query ID“ (interní hash dotazu)
– identifikace dotazu (monitorovací nástroje)
– nestabilní mezi major verzemi / platformami
● možnost získat statistiky bez textů dotazů
SELECT * FROM pg_stat_statements(false);
– úspornější fungování monitorovacích nástrojů
34.
Replikace a recovery
● přesun tablespaces v pg_basebackup
CREATE TABLESPACE ... LOCATION '...';
– jiné rozložení disku, stejná mašina => :-(
pg_basebackup -T olddir=newdir
● time-delayed standby (recovery.conf)
recovery_min_apply_delay=3600000
● pg_stat_archiver
– čas/počet archivovaných WAL segmentů (atd.)
– úspěšné i neúspěšné pokusy
35.
Infrastruktura
● základ logické replikace
– zpětná extrakce změn z transakčního logu
– základy v 9.4, další patche (9.5)
– alternativa k Slony, londiste, ...
● replikační sloty
– flexibilní zachovávání WAL segmentů
– alternativa wal_keep_segments / archive_command
– alternativa hot_standby_feedback /
vacuum_defer_cleanup_age
36.
Infrastruktura
● background workers
– uživatelské procesy spravované databází
(extensions)
– dynamická registrace, spouštění, ukončování
– max_worker_processes
– ...
– vnímáno jako základ pro „Parallel Query“
37.
Spousta dalšího ...
http://www.postgresql.org/docs/9.4/static/release-9-4.html
● spousta malých změn a vylepšení
– výkonnostní vylepšení
– zjednodušení práce
– atd. atd.
38.
JSONB
Dokumentace
http://www.postgresql.org/docs/9.4/static/datatype-json.html
NoSQL on ACID
https://wiki.postgresql.org/images/d/de/NoSQL_training_-_pgconf.eu.pdf
39.
KV a dokumenty v PostgreSQL
HSTORE
● kolekce key-value
– pouze řetězce, jedna úroveň (bez vnoření)
● jednoduchá definice, rychlý, snadná práce
● PostgreSQL 8.2 (2006)
– predatuje mnohé NoSQL řešení
● ideální pro „řídké“ kolekce hodnot
– spousta sloupců, neznámé sloupce, ...
40.
KV a dokumenty v PostgreSQL
JSON
● hierarchický model dokumentů
● 9.2 – samostatný datový typ
– víceméně jenom validace vstupu, minimum funkcí
– možnost psát funkce v PL/V8, PL/Perl, …
● 9.3 – doplněny operátory / funkce pro manipulaci, ...
JSONB
● binární reprezentace JSON (neplést s BSON)
● rychlejší, širší paleta operátorů, robustnější
● PostgreSQL 9.4 (namísto vyvíjeného HSTORE2)
43.
funkce a operátory
● http://www.postgresql.org/docs/9.4/static/functions-json.html
● extrakce hodnot z JSON dokumentů
-> jako JSON dokument
#> jako JSON dokument
->> jako text
#>> jako text
● containment a existence
@> containment (sub-dokument)
? existence klíče
?| existence (alespoň jeden klíč)
?& existence (všechny klíče)
48.
Mailing list archive
CREATE TABLE messages (
id integer PRIMARY KEY,
parent_id integer,
thread_id integer,
list varchar(32) NOT NULL,
message_id varchar(200),
...
sent timestamp,
author text,
subject text,
headers jsonb,
body_plain text,
subject_tsvector tsvector,
body_tsvector tsvector
);
49.
JSONB / diskový prostor
List of relations
Schema | Name | Size
--------+----------------------+---------
public | headers_jsonb | 1244 MB
public | headers_jsonb_beta_2 | 1330 MB
public | headers_json | 1517 MB
public | headers_text | 1517 MB
dump 1567 MB
50.
Dotazování
SELECT COUNT(*) FROM messages
WHERE headers ? 'bcc';
SELECT (headers->>'message-id') AS mid FROM messages
WHERE headers ? 'bcc';
SELECT COUNT(*) FROM messages
WHERE headers @> '{"from" : "tv@fuzzy.cz"}';
QUERY PLAN
------------------------------------------------------------------
Aggregate (cost=177501.99..177502.00 rows=1 width=0)
-> Seq Scan on messages (cost=0.00..177499.70 rows=917
width=0)
Filter: (headers @> '{"from": "tv@fuzzy.cz"}'::jsonb)
Planning time: 0.178 ms
(4 rows)
51.
Indexování / btree
● nesmysl indexovat celé JSON dokumenty
– ale indexy nad výrazy lze použít
CREATE INDEX messages_cc_idx
ON messages ((headers->>'cc'));
SELECT * FROM messages
WHERE headers->>'cc' = 'tv@fuzzy.cz';
QUERY PLAN
-------------------------------------------------------------------------
Bitmap Heap Scan on messages (cost=200.09..16121.34 rows=4585 width=1529)
Recheck Cond: ((headers ->> 'cc'::text) = 'tv@fuzzy.cz'::text)
-> Bitmap Index Scan on ttt (cost=0.00..198.94 rows=4585 width=0)
Index Cond: ((headers ->> 'cc'::text) = 'tv@fuzzy.cz'::text)
Planning time: 1.044 ms
(5 rows)
52.
Indexování / GIN
CREATE INDEX messages_gin_idx
ON messages USING gin(headers);
SELECT * FROM messages
WHERE headers @> '{"cc" : "tv@fuzzy.cz"}';
QUERY PLAN
--------------------------------------------------------------------------
Bitmap Heap Scan on messages (cost=51.11..3518.80 rows=917 width=1529)
Recheck Cond: (headers @> '{"cc": "tv@fuzzy.cz"}'::jsonb)
-> Bitmap Index Scan on messages_gin_idx (cost=0.00..50.88 rows=917
width=0)
Index Cond: (headers @> '{"cc": "tv@fuzzy.cz"}'::jsonb)
Planning time: 0.135 ms
(5 rows)
53.
Indexování / GIN
● jsonb_ops
– výchozí operator class
– všechny základní operátory @> ? ?| ?&
● jsonb_path_ops
– menší, rychlejší indexy
– pouze @> operátor
CREATE INDEX headers_path_idx ON messages
USING gin(headers jsonb_path_ops);
● možnost subdocument indexů
CREATE INDEX messages_cc_idx ON messages
USING gin((headers->'cc'));
54.
Indexování / GIN
List of relations
Schema | Name | Size
--------+---------------------------+--------
public | messages_btree_idx | 64 MB
public | messages_gin_idx | 503 MB
public | messages_gin_path_idx | 270 MB
public | messages_hash_id_key | 67 MB
public | messages_pkey | 36 MB
public | messages_cc_idx | 25 MB
(4 rows)
55.
PostgrteSQL NoSQL benchmark
https://github.com/EnterpriseDB/pg_nosql_benchmark
http://bit.ly/1rXinmp / http://bit.ly/1t2jG1r
(nižší hodnoty jsou lepší)
56.
Fulltext benchmark
● fulltextové vyhledávání v e-mailovém archivu
● kombinace slov s různou frekvencí
● 33k reálných dotazů z postgresql.org
SELECT id FROM messages
WHERE body_fts @@ ('high & performance')::tsquery
ORDER BY ts_rank(body_fts, ('high & performance')::tsquery)
DESC LIMIT 100;
57.
9.4 durations, divided by 9.3 durations (e.g. 0.1 means 10x speedup)
1.8
1.6
1.4
1.2
1
0.8
0.6
0.4
0.2
0
Fulltext benchmark / 9.3 vs. 9.4 (GIN fastscan)
0.1 1 10 100 1000
duration on 9.3 [miliseconds, log scale]
9.4 duration (relative to 9.3)