SlideShare ist ein Scribd-Unternehmen logo
1 von 57
Downloaden Sie, um offline zu lesen
PostgreSQL 9.4 - Novinky (a JSONB) 
Tomáš Vondra, GoodData (tomas.vondra@gooddata.com) 
http://blog.pgaddict.com (tomas@pgaddict.com)
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
Postup vývoje 9.4 
2013 červen 9.3 branch 
2013 červen commitfest #1 
2013 září commitfest #2 
2013 listopad commitfest #3 
2014 leden commitfest #4 
2014 květen beta 1 
2014 červenec beta 2 
2014 říjen beta 3 
2014 listopad (?) PostgreSQL 9.4.0
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 ;-)
https://www.openhub.net/p/postgres
Takže co je vlastně nového? 
● vývojářské / SQL vlastnosti 
● DBA a administrace 
● replikace a recovery 
● infrastruktura
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)
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;
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! )
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;
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í )
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;
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)
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);
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;
unnest 
SELECT unnest(ARRAY[1,2,3]) AS a; 
a 
--- 
1 
2 
3 
(3 rows)
unnest 
SELECT unnest(ARRAY[1,2,3]) AS a, 
unnest(ARRAY[4,5,6]) AS b;
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)
unnest 
SELECT unnest(ARRAY[1,2,3]) AS a, 
unnest(ARRAY[4,5]) AS b;
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)
unnest 
SELECT * 
FROM unnest(ARRAY[1,2,3], ARRAY[4,5]) AS t(a,b); 
a | b 
---+--- 
1 | 4 
2 | 5 
3 | 
(3 rows)
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)
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);
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 
...
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)
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)
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;
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)
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ší)
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();
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)
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)
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ů
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
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
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“
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.
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
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, ...
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)
JSONB příklad 
CREATE TABLE json_data (data JSONB); 
INSERT INTO json_data (data) VALUES 
('{"name": "Apple Phone", 
"type": "phone", 
"brand": "ACME", 
"price": 200, 
"available": true, 
"warranty_years": 1}');
JSONB příklad 
CREATE TABLE json_data (data JSONB); 
INSERT INTO json_data (data) VALUES 
('{"full name": "John Joseph Carl Salinger", 
"names": [ 
{"type": "firstname", "value": "John"}, 
{"type": "middlename", "value": "Joseph"}, 
{"type": "middlename", "value": "Carl"}, 
{"type": "lastname", "value": "Salinger"} 
]}');
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)
extrakce hodnot (jako JSON) 
SELECT '{"a" : {"b" : "c"}}'::jsonb -> 'a'; 
{"b": "c"} 
SELECT '{"a" : {"b" : "c"}}'::jsonb -> 'a' -> 'b'; 
"c" 
SELECT '{"a" : {"b" : "c"}}'::jsonb #> '{a, b}'; 
SELECT '{"a" : {"b" : "c"}}'::jsonb #> ARRAY['a', 'b']; 
"c"
containment & existence 
SELECT '{"a":1, "b":2}'::jsonb @> '{"b":2}'::jsonb; 
true 
SELECT '{"a":1, "b":2}'::jsonb @> '{"b":3}'::jsonb; 
false 
SELECT '{"a":1, "b":2}'::jsonb ? 'a'; 
true 
SELECT '{"a":1, "b":2}'::jsonb ?| ARRAY['a', 'c']; 
true 
SELECT '{"a":1, "b":2}'::jsonb ?& ARRAY['a', 'c']; 
false
processing functions 
● to_json 
● array_to_json 
● row_to_json 
● json_build_array 
● json_build_object 
● json_object 
● json_array_length 
● json_each 
● json_each_text 
● json_extract_path 
● json_extract_path_text 
● json_object_keys 
● json_populate_record 
● json_populate_recordset 
● json_array_elements 
● json_array_elements_text 
● json_typeof 
● json_to_record 
● json_to_recordset 
http://www.postgresql.org/docs/9.4/static/functions-json.html
processing functions 
● to_json 
● array_to_json 
● row_to_json 
● json_build_array 
● json_build_object 
● json_object 
● jsonb_array_length 
● jsonb_each 
● jsonb_each_text 
● jsonb_extract_path 
● jsonb_extract_path_text 
● jsonb_object_keys 
● jsonb_populate_record 
● jsonb_populate_recordset 
● jsonb_array_elements 
● jsonb_array_elements_text 
● jsonb_typeof 
● jsonb_to_record 
● jsonb_to_recordset 
http://www.postgresql.org/docs/9.4/static/functions-json.html
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 
);
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
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)
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)
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)
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'));
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)
PostgrteSQL NoSQL benchmark 
https://github.com/EnterpriseDB/pg_nosql_benchmark 
http://bit.ly/1rXinmp / http://bit.ly/1t2jG1r 
(nižší hodnoty jsou lepší)
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;
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)

Weitere ähnliche Inhalte

Andere mochten auch

b tree file system report
b tree file system reportb tree file system report
b tree file system report
Dinesh Gupta
 
PoPostgreSQL Web Projects: From Start to FinishStart To Finish
PoPostgreSQL Web Projects: From Start to FinishStart To FinishPoPostgreSQL Web Projects: From Start to FinishStart To Finish
PoPostgreSQL Web Projects: From Start to FinishStart To Finish
elliando dias
 
How does PostgreSQL work with disks: a DBA's checklist in detail. PGConf.US 2015
How does PostgreSQL work with disks: a DBA's checklist in detail. PGConf.US 2015How does PostgreSQL work with disks: a DBA's checklist in detail. PGConf.US 2015
How does PostgreSQL work with disks: a DBA's checklist in detail. PGConf.US 2015
PostgreSQL-Consulting
 

Andere mochten auch (17)

PostgreSQL na EXT4, XFS, BTRFS a ZFS / FOSDEM PgDay 2016
PostgreSQL na EXT4, XFS, BTRFS a ZFS / FOSDEM PgDay 2016PostgreSQL na EXT4, XFS, BTRFS a ZFS / FOSDEM PgDay 2016
PostgreSQL na EXT4, XFS, BTRFS a ZFS / FOSDEM PgDay 2016
 
5 Steps to PostgreSQL Performance
5 Steps to PostgreSQL Performance5 Steps to PostgreSQL Performance
5 Steps to PostgreSQL Performance
 
Presentation db2 best practices for optimal performance
Presentation   db2 best practices for optimal performancePresentation   db2 best practices for optimal performance
Presentation db2 best practices for optimal performance
 
Postgres in Production - Best Practices 2014
Postgres in Production - Best Practices 2014Postgres in Production - Best Practices 2014
Postgres in Production - Best Practices 2014
 
PostgreSQL + ZFS best practices
PostgreSQL + ZFS best practicesPostgreSQL + ZFS best practices
PostgreSQL + ZFS best practices
 
Spaß mit PostgreSQL
Spaß mit PostgreSQLSpaß mit PostgreSQL
Spaß mit PostgreSQL
 
Linux slides 2013_upload
Linux slides 2013_uploadLinux slides 2013_upload
Linux slides 2013_upload
 
PostgreSQL on EXT4, XFS, BTRFS and ZFS
PostgreSQL on EXT4, XFS, BTRFS and ZFSPostgreSQL on EXT4, XFS, BTRFS and ZFS
PostgreSQL on EXT4, XFS, BTRFS and ZFS
 
b tree file system report
b tree file system reportb tree file system report
b tree file system report
 
PoPostgreSQL Web Projects: From Start to FinishStart To Finish
PoPostgreSQL Web Projects: From Start to FinishStart To FinishPoPostgreSQL Web Projects: From Start to FinishStart To Finish
PoPostgreSQL Web Projects: From Start to FinishStart To Finish
 
82599 sriov vm configuration notes
82599 sriov vm configuration notes82599 sriov vm configuration notes
82599 sriov vm configuration notes
 
Best Practices for a Complete Postgres Enterprise Architecture Setup
Best Practices for a Complete Postgres Enterprise Architecture SetupBest Practices for a Complete Postgres Enterprise Architecture Setup
Best Practices for a Complete Postgres Enterprise Architecture Setup
 
How does PostgreSQL work with disks: a DBA's checklist in detail. PGConf.US 2015
How does PostgreSQL work with disks: a DBA's checklist in detail. PGConf.US 2015How does PostgreSQL work with disks: a DBA's checklist in detail. PGConf.US 2015
How does PostgreSQL work with disks: a DBA's checklist in detail. PGConf.US 2015
 
Performance improvements in PostgreSQL 9.5 and beyond
Performance improvements in PostgreSQL 9.5 and beyondPerformance improvements in PostgreSQL 9.5 and beyond
Performance improvements in PostgreSQL 9.5 and beyond
 
Postgresql on NFS - J.Battiato, pgday2016
Postgresql on NFS - J.Battiato, pgday2016Postgresql on NFS - J.Battiato, pgday2016
Postgresql on NFS - J.Battiato, pgday2016
 
MySQL技术分享:一步到位实现mysql优化
MySQL技术分享:一步到位实现mysql优化MySQL技术分享:一步到位实现mysql优化
MySQL技术分享:一步到位实现mysql优化
 
雑なMySQLパフォーマンスチューニング
雑なMySQLパフォーマンスチューニング雑なMySQLパフォーマンスチューニング
雑なMySQLパフォーマンスチューニング
 

Ähnlich wie Novinky v PostgreSQL 9.4 a JSONB

Ähnlich wie Novinky v PostgreSQL 9.4 a JSONB (10)

Django
DjangoDjango
Django
 
Doctrine ORM & model
Doctrine ORM & modelDoctrine ORM & model
Doctrine ORM & model
 
Miroslav Bajtoš - Nativní async/await v Node.js - už tam jsme?
Miroslav Bajtoš - Nativní async/await v Node.js - už tam jsme?Miroslav Bajtoš - Nativní async/await v Node.js - už tam jsme?
Miroslav Bajtoš - Nativní async/await v Node.js - už tam jsme?
 
Data Restart 2023: Václav Ráš - 10 tipů, jak pracovat s BigQuery
Data Restart 2023: Václav Ráš - 10 tipů, jak pracovat s BigQueryData Restart 2023: Václav Ráš - 10 tipů, jak pracovat s BigQuery
Data Restart 2023: Václav Ráš - 10 tipů, jak pracovat s BigQuery
 
Petr Heinz - Čisté testy, dobré testy
Petr Heinz - Čisté testy, dobré testyPetr Heinz - Čisté testy, dobré testy
Petr Heinz - Čisté testy, dobré testy
 
201502.ReinIT.Dev
201502.ReinIT.Dev201502.ReinIT.Dev
201502.ReinIT.Dev
 
Novinky Oracle db 12c
Novinky Oracle db 12cNovinky Oracle db 12c
Novinky Oracle db 12c
 
Czech Sun Training Day 2008 - Java Enterprise System
Czech Sun Training Day 2008 - Java Enterprise SystemCzech Sun Training Day 2008 - Java Enterprise System
Czech Sun Training Day 2008 - Java Enterprise System
 
ClojureScript
ClojureScriptClojureScript
ClojureScript
 
Clean code
Clean codeClean code
Clean code
 

Mehr von Tomas Vondra

Mehr von Tomas Vondra (13)

CREATE STATISTICS - What is it for? (PostgresLondon)
CREATE STATISTICS - What is it for? (PostgresLondon)CREATE STATISTICS - What is it for? (PostgresLondon)
CREATE STATISTICS - What is it for? (PostgresLondon)
 
Data corruption
Data corruptionData corruption
Data corruption
 
CREATE STATISTICS - what is it for?
CREATE STATISTICS - what is it for?CREATE STATISTICS - what is it for?
CREATE STATISTICS - what is it for?
 
DB vs. encryption
DB vs. encryptionDB vs. encryption
DB vs. encryption
 
PostgreSQL na EXT4, XFS, BTRFS a ZFS / OpenAlt
PostgreSQL na EXT4, XFS, BTRFS a ZFS / OpenAltPostgreSQL na EXT4, XFS, BTRFS a ZFS / OpenAlt
PostgreSQL na EXT4, XFS, BTRFS a ZFS / OpenAlt
 
Postgresql na EXT3/4, XFS, BTRFS a ZFS
Postgresql na EXT3/4, XFS, BTRFS a ZFSPostgresql na EXT3/4, XFS, BTRFS a ZFS
Postgresql na EXT3/4, XFS, BTRFS a ZFS
 
PostgreSQL performance archaeology
PostgreSQL performance archaeologyPostgreSQL performance archaeology
PostgreSQL performance archaeology
 
Výkonnostní archeologie
Výkonnostní archeologieVýkonnostní archeologie
Výkonnostní archeologie
 
Český fulltext a sdílené slovníky
Český fulltext a sdílené slovníkyČeský fulltext a sdílené slovníky
Český fulltext a sdílené slovníky
 
SSD vs HDD / WAL, indexes and fsync
SSD vs HDD / WAL, indexes and fsyncSSD vs HDD / WAL, indexes and fsync
SSD vs HDD / WAL, indexes and fsync
 
Čtení explain planu (CSPUG 21.6.2011)
Čtení explain planu (CSPUG 21.6.2011)Čtení explain planu (CSPUG 21.6.2011)
Čtení explain planu (CSPUG 21.6.2011)
 
Replikace (CSPUG 19.4.2011)
Replikace (CSPUG 19.4.2011)Replikace (CSPUG 19.4.2011)
Replikace (CSPUG 19.4.2011)
 
PostgreSQL / Performance monitoring
PostgreSQL / Performance monitoringPostgreSQL / Performance monitoring
PostgreSQL / Performance monitoring
 

Novinky v PostgreSQL 9.4 a JSONB

  • 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
  • 3. Postup vývoje 9.4 2013 červen 9.3 branch 2013 červen commitfest #1 2013 září commitfest #2 2013 listopad commitfest #3 2014 leden commitfest #4 2014 květen beta 1 2014 červenec beta 2 2014 říjen beta 3 2014 listopad (?) PostgreSQL 9.4.0
  • 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)
  • 41. JSONB příklad CREATE TABLE json_data (data JSONB); INSERT INTO json_data (data) VALUES ('{"name": "Apple Phone", "type": "phone", "brand": "ACME", "price": 200, "available": true, "warranty_years": 1}');
  • 42. JSONB příklad CREATE TABLE json_data (data JSONB); INSERT INTO json_data (data) VALUES ('{"full name": "John Joseph Carl Salinger", "names": [ {"type": "firstname", "value": "John"}, {"type": "middlename", "value": "Joseph"}, {"type": "middlename", "value": "Carl"}, {"type": "lastname", "value": "Salinger"} ]}');
  • 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)
  • 44. extrakce hodnot (jako JSON) SELECT '{"a" : {"b" : "c"}}'::jsonb -> 'a'; {"b": "c"} SELECT '{"a" : {"b" : "c"}}'::jsonb -> 'a' -> 'b'; "c" SELECT '{"a" : {"b" : "c"}}'::jsonb #> '{a, b}'; SELECT '{"a" : {"b" : "c"}}'::jsonb #> ARRAY['a', 'b']; "c"
  • 45. containment & existence SELECT '{"a":1, "b":2}'::jsonb @> '{"b":2}'::jsonb; true SELECT '{"a":1, "b":2}'::jsonb @> '{"b":3}'::jsonb; false SELECT '{"a":1, "b":2}'::jsonb ? 'a'; true SELECT '{"a":1, "b":2}'::jsonb ?| ARRAY['a', 'c']; true SELECT '{"a":1, "b":2}'::jsonb ?& ARRAY['a', 'c']; false
  • 46. processing functions ● to_json ● array_to_json ● row_to_json ● json_build_array ● json_build_object ● json_object ● json_array_length ● json_each ● json_each_text ● json_extract_path ● json_extract_path_text ● json_object_keys ● json_populate_record ● json_populate_recordset ● json_array_elements ● json_array_elements_text ● json_typeof ● json_to_record ● json_to_recordset http://www.postgresql.org/docs/9.4/static/functions-json.html
  • 47. processing functions ● to_json ● array_to_json ● row_to_json ● json_build_array ● json_build_object ● json_object ● jsonb_array_length ● jsonb_each ● jsonb_each_text ● jsonb_extract_path ● jsonb_extract_path_text ● jsonb_object_keys ● jsonb_populate_record ● jsonb_populate_recordset ● jsonb_array_elements ● jsonb_array_elements_text ● jsonb_typeof ● jsonb_to_record ● jsonb_to_recordset http://www.postgresql.org/docs/9.4/static/functions-json.html
  • 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)