SlideShare a Scribd company logo
CONQUERING
JSONB IN
POSTGRESQL
Ines Panker
Why did PostgreSQL add a
JSON data type?
Postgre SQL and NoSQL
Postgre 9.4 (December 2014) JSONB: Binary format, slower input, faster processing
JSON: Exact copy, same orderPostgre 9.2
No explicit
schema
Key-Value pairs in JSON are equal to
Key-Value pairs in columns
CREATE TABLE "PaymentRequest" (
"ID" bigint PRIMARY KEY NOT NULL,
"Created" timestamp without time zone,
"LastEdited" timestamp without time zone,
"Identifier" character varying(50),
"FinalPrice" double precision,
...,
"DeliveryTypeJSON" jsonb,
"DeliveryAddressJSON" jsonb,
"InvoiceAddressJSON" jsonb,
"PromotionCodeJSON" jsonb,
"PaymentJSON" jsonb);
CREATE TABLE "PaymentRequestEntry" (
"ID" bigint PRIMARY KEY NOT NULL,
"CartCount" integer DEFAULT 0,
"PriceWithTax" double precision,
"FullPriceWithTax" double precision,
"PriceNoTax" double precision,
"FullPriceNoTax" double precision,
...,
"ShopProductJSON" jsonb,
"PaymentRequestID" integer DEFAULT 0,
"VoucherID" integer DEFAULT 0
);
class ShopProduct{
private function DataForInvoice() {
$data = array(
'SKU' => $this->SKU,
'Title' => $this->LocaleTitle(),
'Variant' => $this->Variant,
'PriceWithTax' => $this->PriceWithTax(),
'PriceNoTax' => $this->PriceNoTax(),
'DiscountPriceWithTax'=> $this->PriceWithTax(true),
'DiscountPriceNoTax' => $this->PriceNoTax(true),
'Promotion' => $this->Promotion()->DataForInvoice(),
'TaxRate' => $this->TaxRate($nice = false),
'TaxPriceOfOne' => $this->TaxOfOneProduct(),
'NoTax' => $this->NoTax(),
'AllowOneStepTransaction' => $this->AllowOneStepTransaction,
'IsVoucher' => $this->IsVoucher,
....
);
return $data;
}
}
INSERT INTO "PaymentRequestEntry" VALUES (
1,
21.60,
24.00,
17.70,
19.67,
...,
'{
"SKU":"LJCRD-24-ADL",
"Title": "Visit Ljubljana Card, 24 hours",
"Variant": "Adult",
"PriceWithTax": 24.00,
"PriceNoTax": 19.67,
...,
"Promotion": {
"Code": "SUMMER17",
"DiscountPercent": 10.00,
"DiscountAmount": null,
"ActiveFrom": "2017-05-15 00:00:00"
"ActiveTo": "2017-06-15 00:00:00"
}
"TaxRate": 0.22
}',
845623
);
ERROR: invalid input syntax for type json
"ShopProductJSON"
-----------------------------------------------
{
"SKU": "LJCRD-24-ADL",
"NoTax": false,
"Title": "Visit Ljubljana Card, 24 hours",
"TaxRate": 0.22,
"Variant": "Adult",
"IsVoucher": false,
"Promotion": {
"Code": "SUMMER17",
"ActiveTo": "2017-06-15 00:00:00",
"ActiveFrom": "2017-05-15 00:00:00",
"DiscountAmount": null,
"DiscountPercent": "10.00"
},
"PriceNoTax": 19.67,
"TaxRateNice": 0.22,
"PriceWithTax": 24.00,
"DiscountPriceNoTax": 17.70,
"DiscountPriceWithTax": 21.60,
"AllowOneStepTransaction": 1,
...
}
SELECT "ShopProductJSON" FROM "PaymentRequestEntry" WHERE "ID" = 1
How to query??
select
"ID",
"WholePriceWithTax",
"NumberOfItems",
"ShopProductJSON"->>'SKU' AS "SKU",
"ShopProductJSON"->>'Title' as "Title",
"ShopProductJSON"->>'PriceWithTax' as "PriceWithTax",
"ShopProductJSON" from "PaymentRequestEntry"
WHERE "PaymentRequestID" = 1
ID
WholePrice
WithTax
NumberOf
Items SKU Title
PriceWith
Tax
1 21.6 1 LJCRD-24-ADL
Visit Ljubljana Card, 2
4 hours
24
2 90 2 TOUR-BIKE-24 Bike tour of Ljubljana 45
3 387 2 WC-17 WebCamp 2017 15
How to query??
(details)
JSON Operators: ->
arrays objects
int text
SELECT '["a",2,"3"]'::json->0 as data
data (json)
------------------
"a"
SELECT '["a",2,"3"]'::json->1 as data
data (json)
------------------
2
SELECT '["a",2,"3"]'::json->2 as data
data (json)
------------------
"3"
SELECT '["a",2,"3"]'::json->'a' as data
data (json)
------------------
SELECT '{"a":1,"b":2}'::json->'b' as data
data (json)
------------------
2
SELECT '{"a":1,"b":{"c":[1,2]}}'::json->'b'
data (json)
------------------
{"c":[1,2]}
json json
JSON Operators: ->>
arrays
int
SELECT '["a",2,"3"]'::json->>0 as data
data (text)
------------------
"a"
SELECT '["a",2,"3"]'::json->>1 > 1
ERROR: operator does not exist: text >
integer
SELECT ('["a",2,"3"]'::json->>1)::int > 1
data (boolean)
---------------
t
SELECT ('["a",2,"3"]'::json->1)::int > 1
ERROR: cannot cast type json to integer
text
JSON Operators: ->>
SELECT '{"a":1,"b":"word"}'::json->>'b'
data (text)
------------------
"word"
SELECT '{"a":1,"b":"word"}'::json->>'b' = 'word'
data(boolean)
-----------
t
SELECT
'{
"identifier":1mo3j4,
"items":[
{
"mon":"Monday",
"tue":"Tuesday"
},
{
"jan":"january",
"feb":"february"
}
]
}'::json->'items'->0->>'tue'
data (text)
--------------
"Tuesday"
objects
text text
JSON Operators: #>, #>>
SELECT
'{
"id":1,
"items":[
{
"mon":"Monday",
"tue":"Tuesday"
},
{
"jan":"january",
"feb":"february"
}
]
}'::json #>> '{items,0,tue}'
data (text)
--------------
"Tuesday"
SELECT
'{
"id":1,
"items":[
{
"mon":"Monday",
"tue":"Tuesday"
},
{
"jan":"january",
"feb":"february"
}
]
}'::json ->'items'->0->>'tue'
data (text)
--------------
"Tuesday"
objects
array of text text
JSONB Operators: @>, ?
SELECT
'{
"promotion":
{
"code":"SUMMER17",
"discount":"10"
}
}'::jsonb ? 'promotion'
SELECT
'{
"promotion":
{
"code":"SUMMER17",
"discount":"10"
}
}'::jsonb->'promotion' ? 'code'
SELECT
'{
"id":1,
"promotion":
{
"code":"SUMMER17",
"discount":"10"
}
}'::jsonb @> '{"promotion":{"code":
"SUMMER17"}}'
data (boolean)
--------------
t
objects
text boolean
objects
jsonb boolean
SELECT count("ID") as number_of_products_promo_was_used
FROM "PaymentRequestEntry"
WHERE "ShopProductJSON" @> '{"Promotion":{"Code": "SUMMER17"}}'
{
"SKU": "LJCRD-24-ADL",
"IsVoucher": false,
"Promotion": {
"Code": "SUMMER17",
},
"PriceNoTax": "19.67",
"TaxRateNice": "0.22",
"PriceWithTax": "24.00",
"DiscountPriceNoTax": "10.00",
"DiscountPriceWithTax": "10.00",
}
SELECT
"PaymentRequestID",
sum(("ShopProductJSON"->>'PriceWithTax')::float)
- sum(("ShopProductJSON"->>'DiscountPriceWithTax')::float) as money_saved
FROM "PaymentRequestEntry"
WHERE "ShopProductJSON" @> '{"Promotion":{"Code": "SUMMER17"}}‘
GROUP BY "PaymentRequestID"
PaymentRequestID money_saved
845623 5.12
845622 6.01
845625 2.2
...
SELECT
SUM("CartCount") AS number_of_products,
SUM(("ShopProductJSON"->>'PriceWithTax')::float) -
SUM(("ShopProductJSON"->>'DiscountPriceWithTax')::float) AS
money_saved,
r."DeliveryAddressJSON"->>'Country' AS country
FROM "PaymentRequestEntry" e
INNER JOIN "PaymentRequest" r ON r."ID" = e."PaymentRequestID"
WHERE "ShopProductJSON"->'Promotion'->>'Code' = 'SUMMER17'
GROUP BY r."DeliveryAddressJSON"->>'Country'
ORDER BY money_saved
number_of_products money_saved country
481 1503.72 DE
512 1438.56 AT
503 1289.05 IT
...
SELECT
sp."CalculatedPrice",
e."ShopProductJSON"->>'PriceWithTax' as bought_price,
e."Created"
FROM "PaymentRequestEntry" e
INNER JOIN "ShopProduct" sp
ON sp."SKU" = e."ShopProductJSON"->>'SKU'
AND e."ShopProductJSON" @> '{"SKU": "LJCRD-24-ADL"}'
ORDER BY e."Created" desc
CalculatedPrice bought_price Created
24 24 2017-04-21 15:23:01
24 21.6 2017-04-21 15:22:12
...
24 22 2016-12-01 07:17:53
...
EXPLAIN SELECT *
FROM "PaymentRequestEntry"
WHERE "ShopProductJSON" @> '{"Promotion":{"Code": "SUMMER17"}}'
Seq Scan on "PaymentRequestEntry" (cost=0.00..21.02 rows=3 width=100)
Filter: ((("ShopProductJSON" -> 'Promotion'::text) ->> 'Code'::text) =
'SUMMER17'::text)
GIN index
over the
WHOLE JSON
for only 1 key
in the JSON
jsonb_ops :
bigger & more
versatily
jsonb_path_ops:
smaller & supports
only @> querys
EXPLAIN SELECT * FROM "PaymentRequestEntry"
WHERE "ShopProductJSON" @> '{"Promotion":{"Code": "SUMMER17"}}'
Seq Scan on "PaymentRequestEntry" (cost=0.00..511091.51 rows=3662
width=85)
table "PaymentRequestEntry" size: 3635 MB, 2.807.147 rows
CREATE index json_index ON "PaymentRequestEntry"
USING GIN (("ShopProductJSON"->'Promotion'->'Code'))
CREATE index json_index ON "PaymentRequestEntry"
USING GIN ("ShopProductJSON")
@> <@
? ?| ?&
CREATE index json_index ON "PaymentRequestEntry"
USING GIN ("ShopProductJSON" jsonb_path_ops)
@>
indexname num_rows index_size
json_index_ops 2.807.147 10 MB
json_index_path_ops 2.807.147 7.832 MB (-20%)
json_index_column 2.807.147 3.112 MB (-70%)
json_index_column_path 2.807.147 3.112 MB (-70%)
1.
2.
3.
What have we used JSON
data types for so far?
Shop++
Changelog
JSON to Form
{
"type":"object",
"title":"Comment",
"properties":{
"name":{
"title":"Name",
"type":"string"
},
"email":{
"title":"Email",
"type":"string",
"pattern":"^S+@S+$",
"description":"Email will be used for evil."
},
"comment":{
"title":"Comment",
"type":"string",
"maxLength":20,
"validationMessage":"Don't be greedy!"
}
},
"required":[
"name",
"email",
"comment"
]
}
Evet Recurence Rules
REST API calls
The End
Ad

Recommended

Embedding a language into string interpolator
Embedding a language into string interpolator
Michael Limansky
 
Mobile Web 5.0
Mobile Web 5.0
Michael Galpin
 
MongoDB .local Paris 2020: La puissance du Pipeline d'Agrégation de MongoDB
MongoDB .local Paris 2020: La puissance du Pipeline d'Agrégation de MongoDB
MongoDB
 
Mongo db for c# developers
Mongo db for c# developers
Simon Elliston Ball
 
Spray Json and MongoDB Queries: Insights and Simple Tricks.
Spray Json and MongoDB Queries: Insights and Simple Tricks.
Andrii Lashchenko
 
The Ring programming language version 1.8 book - Part 49 of 202
The Ring programming language version 1.8 book - Part 49 of 202
Mahmoud Samir Fayed
 
quick json parser
quick json parser
Rajesh Putta
 
MongoDB Performance Tuning
MongoDB Performance Tuning
Puneet Behl
 
From mysql to MongoDB(MongoDB2011北京交流会)
From mysql to MongoDB(MongoDB2011北京交流会)
Night Sailer
 
The rise of json in rdbms land jab17
The rise of json in rdbms land jab17
alikonweb
 
2011 Mongo FR - Indexing in MongoDB
2011 Mongo FR - Indexing in MongoDB
antoinegirbal
 
How to leverage what's new in MongoDB 3.6
How to leverage what's new in MongoDB 3.6
Maxime Beugnet
 
Mongoskin - Guilin
Mongoskin - Guilin
Jackson Tian
 
MongoDB Europe 2016 - Debugging MongoDB Performance
MongoDB Europe 2016 - Debugging MongoDB Performance
MongoDB
 
Inside MongoDB: the Internals of an Open-Source Database
Inside MongoDB: the Internals of an Open-Source Database
Mike Dirolf
 
CouchDB on Android
CouchDB on Android
Sven Haiges
 
The Testing Games: Mocking, yay!
The Testing Games: Mocking, yay!
Donny Wals
 
MongoDB Europe 2016 - ETL for Pros – Getting Data Into MongoDB The Right Way
MongoDB Europe 2016 - ETL for Pros – Getting Data Into MongoDB The Right Way
MongoDB
 
"Powerful Analysis with the Aggregation Pipeline (Tutorial)"
"Powerful Analysis with the Aggregation Pipeline (Tutorial)"
MongoDB
 
Data Governance with JSON Schema
Data Governance with JSON Schema
MongoDB
 
Map/Confused? A practical approach to Map/Reduce with MongoDB
Map/Confused? A practical approach to Map/Reduce with MongoDB
Uwe Printz
 
ETL for Pros: Getting Data Into MongoDB
ETL for Pros: Getting Data Into MongoDB
MongoDB
 
MongoDB .local Munich 2019: Aggregation Pipeline Power++: How MongoDB 4.2 Pip...
MongoDB .local Munich 2019: Aggregation Pipeline Power++: How MongoDB 4.2 Pip...
MongoDB
 
Mongo db mug_2012-02-07
Mongo db mug_2012-02-07
Will Button
 
NoSQL を Ruby で実践するための n 個の方法
NoSQL を Ruby で実践するための n 個の方法
Tomohiro Nishimura
 
Nodejs mongoose
Nodejs mongoose
Fin Chen
 
MongoDB Aggregation
MongoDB Aggregation
Amit Ghosh
 
Native json in the Cache' ObjectScript 2016.*
Native json in the Cache' ObjectScript 2016.*
Timur Safin
 
NoSQL для PostgreSQL: Jsquery — язык запросов
NoSQL для PostgreSQL: Jsquery — язык запросов
CodeFest
 
Oh, that ubiquitous JSON !
Oh, that ubiquitous JSON !
Alexander Korotkov
 

More Related Content

What's hot (20)

From mysql to MongoDB(MongoDB2011北京交流会)
From mysql to MongoDB(MongoDB2011北京交流会)
Night Sailer
 
The rise of json in rdbms land jab17
The rise of json in rdbms land jab17
alikonweb
 
2011 Mongo FR - Indexing in MongoDB
2011 Mongo FR - Indexing in MongoDB
antoinegirbal
 
How to leverage what's new in MongoDB 3.6
How to leverage what's new in MongoDB 3.6
Maxime Beugnet
 
Mongoskin - Guilin
Mongoskin - Guilin
Jackson Tian
 
MongoDB Europe 2016 - Debugging MongoDB Performance
MongoDB Europe 2016 - Debugging MongoDB Performance
MongoDB
 
Inside MongoDB: the Internals of an Open-Source Database
Inside MongoDB: the Internals of an Open-Source Database
Mike Dirolf
 
CouchDB on Android
CouchDB on Android
Sven Haiges
 
The Testing Games: Mocking, yay!
The Testing Games: Mocking, yay!
Donny Wals
 
MongoDB Europe 2016 - ETL for Pros – Getting Data Into MongoDB The Right Way
MongoDB Europe 2016 - ETL for Pros – Getting Data Into MongoDB The Right Way
MongoDB
 
"Powerful Analysis with the Aggregation Pipeline (Tutorial)"
"Powerful Analysis with the Aggregation Pipeline (Tutorial)"
MongoDB
 
Data Governance with JSON Schema
Data Governance with JSON Schema
MongoDB
 
Map/Confused? A practical approach to Map/Reduce with MongoDB
Map/Confused? A practical approach to Map/Reduce with MongoDB
Uwe Printz
 
ETL for Pros: Getting Data Into MongoDB
ETL for Pros: Getting Data Into MongoDB
MongoDB
 
MongoDB .local Munich 2019: Aggregation Pipeline Power++: How MongoDB 4.2 Pip...
MongoDB .local Munich 2019: Aggregation Pipeline Power++: How MongoDB 4.2 Pip...
MongoDB
 
Mongo db mug_2012-02-07
Mongo db mug_2012-02-07
Will Button
 
NoSQL を Ruby で実践するための n 個の方法
NoSQL を Ruby で実践するための n 個の方法
Tomohiro Nishimura
 
Nodejs mongoose
Nodejs mongoose
Fin Chen
 
MongoDB Aggregation
MongoDB Aggregation
Amit Ghosh
 
Native json in the Cache' ObjectScript 2016.*
Native json in the Cache' ObjectScript 2016.*
Timur Safin
 
From mysql to MongoDB(MongoDB2011北京交流会)
From mysql to MongoDB(MongoDB2011北京交流会)
Night Sailer
 
The rise of json in rdbms land jab17
The rise of json in rdbms land jab17
alikonweb
 
2011 Mongo FR - Indexing in MongoDB
2011 Mongo FR - Indexing in MongoDB
antoinegirbal
 
How to leverage what's new in MongoDB 3.6
How to leverage what's new in MongoDB 3.6
Maxime Beugnet
 
Mongoskin - Guilin
Mongoskin - Guilin
Jackson Tian
 
MongoDB Europe 2016 - Debugging MongoDB Performance
MongoDB Europe 2016 - Debugging MongoDB Performance
MongoDB
 
Inside MongoDB: the Internals of an Open-Source Database
Inside MongoDB: the Internals of an Open-Source Database
Mike Dirolf
 
CouchDB on Android
CouchDB on Android
Sven Haiges
 
The Testing Games: Mocking, yay!
The Testing Games: Mocking, yay!
Donny Wals
 
MongoDB Europe 2016 - ETL for Pros – Getting Data Into MongoDB The Right Way
MongoDB Europe 2016 - ETL for Pros – Getting Data Into MongoDB The Right Way
MongoDB
 
"Powerful Analysis with the Aggregation Pipeline (Tutorial)"
"Powerful Analysis with the Aggregation Pipeline (Tutorial)"
MongoDB
 
Data Governance with JSON Schema
Data Governance with JSON Schema
MongoDB
 
Map/Confused? A practical approach to Map/Reduce with MongoDB
Map/Confused? A practical approach to Map/Reduce with MongoDB
Uwe Printz
 
ETL for Pros: Getting Data Into MongoDB
ETL for Pros: Getting Data Into MongoDB
MongoDB
 
MongoDB .local Munich 2019: Aggregation Pipeline Power++: How MongoDB 4.2 Pip...
MongoDB .local Munich 2019: Aggregation Pipeline Power++: How MongoDB 4.2 Pip...
MongoDB
 
Mongo db mug_2012-02-07
Mongo db mug_2012-02-07
Will Button
 
NoSQL を Ruby で実践するための n 個の方法
NoSQL を Ruby で実践するための n 個の方法
Tomohiro Nishimura
 
Nodejs mongoose
Nodejs mongoose
Fin Chen
 
MongoDB Aggregation
MongoDB Aggregation
Amit Ghosh
 
Native json in the Cache' ObjectScript 2016.*
Native json in the Cache' ObjectScript 2016.*
Timur Safin
 

Similar to Conquering JSONB in PostgreSQL (20)

NoSQL для PostgreSQL: Jsquery — язык запросов
NoSQL для PostgreSQL: Jsquery — язык запросов
CodeFest
 
Oh, that ubiquitous JSON !
Oh, that ubiquitous JSON !
Alexander Korotkov
 
Webscale PostgreSQL - JSONB and Horizontal Scaling Strategies
Webscale PostgreSQL - JSONB and Horizontal Scaling Strategies
Jonathan Katz
 
CREATE INDEX … USING VODKA. VODKA CONNECTING INDEXES, Олег Бартунов, Александ...
CREATE INDEX … USING VODKA. VODKA CONNECTING INDEXES, Олег Бартунов, Александ...
Ontico
 
How to Use JSON in MySQL Wrong
How to Use JSON in MySQL Wrong
Karwin Software Solutions LLC
 
Postgre(No)SQL - A JSON journey
Postgre(No)SQL - A JSON journey
Nicola Moretto
 
BGOUG15: JSON support in MySQL 5.7
BGOUG15: JSON support in MySQL 5.7
Georgi Kodinov
 
PostgreSQL 9.4 JSON Types and Operators
PostgreSQL 9.4 JSON Types and Operators
Nicholas Kiraly
 
Oracle Database - JSON and the In-Memory Database
Oracle Database - JSON and the In-Memory Database
Marco Gralike
 
PostgreSQLからMongoDBへ
PostgreSQLからMongoDBへ
Basuke Suzuki
 
Json at work overview and ecosystem-v2.0
Json at work overview and ecosystem-v2.0
Boulder Java User's Group
 
UKOUG Tech14 - Getting Started With JSON in the Database
UKOUG Tech14 - Getting Started With JSON in the Database
Marco Gralike
 
Starting with JSON Path Expressions in Oracle 12.1.0.2
Starting with JSON Path Expressions in Oracle 12.1.0.2
Marco Gralike
 
Json
Json
Raphael Wanjiku
 
NodeUkraine - Postgresql для хипстеров или почему ваш следующий проект должен...
NodeUkraine - Postgresql для хипстеров или почему ваш следующий проект должен...
DmitryChirkin1
 
Validating JSON -- Percona Live 2021 presentation
Validating JSON -- Percona Live 2021 presentation
Dave Stokes
 
MongoDB
MongoDB
Steve Klabnik
 
JSON in MySQL and MariaDB Databases
JSON in MySQL and MariaDB Databases
Federico Razzoli
 
MySQL 5.7 NF – JSON Datatype 활용
MySQL 5.7 NF – JSON Datatype 활용
I Goo Lee
 
Gson
Gson
哲偉 楊
 
NoSQL для PostgreSQL: Jsquery — язык запросов
NoSQL для PostgreSQL: Jsquery — язык запросов
CodeFest
 
Webscale PostgreSQL - JSONB and Horizontal Scaling Strategies
Webscale PostgreSQL - JSONB and Horizontal Scaling Strategies
Jonathan Katz
 
CREATE INDEX … USING VODKA. VODKA CONNECTING INDEXES, Олег Бартунов, Александ...
CREATE INDEX … USING VODKA. VODKA CONNECTING INDEXES, Олег Бартунов, Александ...
Ontico
 
Postgre(No)SQL - A JSON journey
Postgre(No)SQL - A JSON journey
Nicola Moretto
 
BGOUG15: JSON support in MySQL 5.7
BGOUG15: JSON support in MySQL 5.7
Georgi Kodinov
 
PostgreSQL 9.4 JSON Types and Operators
PostgreSQL 9.4 JSON Types and Operators
Nicholas Kiraly
 
Oracle Database - JSON and the In-Memory Database
Oracle Database - JSON and the In-Memory Database
Marco Gralike
 
PostgreSQLからMongoDBへ
PostgreSQLからMongoDBへ
Basuke Suzuki
 
UKOUG Tech14 - Getting Started With JSON in the Database
UKOUG Tech14 - Getting Started With JSON in the Database
Marco Gralike
 
Starting with JSON Path Expressions in Oracle 12.1.0.2
Starting with JSON Path Expressions in Oracle 12.1.0.2
Marco Gralike
 
NodeUkraine - Postgresql для хипстеров или почему ваш следующий проект должен...
NodeUkraine - Postgresql для хипстеров или почему ваш следующий проект должен...
DmitryChirkin1
 
Validating JSON -- Percona Live 2021 presentation
Validating JSON -- Percona Live 2021 presentation
Dave Stokes
 
JSON in MySQL and MariaDB Databases
JSON in MySQL and MariaDB Databases
Federico Razzoli
 
MySQL 5.7 NF – JSON Datatype 활용
MySQL 5.7 NF – JSON Datatype 활용
I Goo Lee
 
Ad

Recently uploaded (20)

Center Enamel can Provide Aluminum Dome Roofs for diesel tank.docx
Center Enamel can Provide Aluminum Dome Roofs for diesel tank.docx
CenterEnamel
 
special_edition_using_visual_foxpro_6.pdf
special_edition_using_visual_foxpro_6.pdf
Shabista Imam
 
Introduction to sensing and Week-1.pptx
Introduction to sensing and Week-1.pptx
KNaveenKumarECE
 
Machine Learning - Classification Algorithms
Machine Learning - Classification Algorithms
resming1
 
Learning – Types of Machine Learning – Supervised Learning – Unsupervised UNI...
Learning – Types of Machine Learning – Supervised Learning – Unsupervised UNI...
23Q95A6706
 
Fundamentals of Digital Design_Class_21st May - Copy.pptx
Fundamentals of Digital Design_Class_21st May - Copy.pptx
drdebarshi1993
 
Abraham Silberschatz-Operating System Concepts (9th,2012.12).pdf
Abraham Silberschatz-Operating System Concepts (9th,2012.12).pdf
Shabista Imam
 
Deep Learning for Natural Language Processing_FDP on 16 June 2025 MITS.pptx
Deep Learning for Natural Language Processing_FDP on 16 June 2025 MITS.pptx
resming1
 
Tesla-Stock-Analysis-and-Forecast.pptx (1).pptx
Tesla-Stock-Analysis-and-Forecast.pptx (1).pptx
moonsony54
 
Industry 4.o the fourth revolutionWeek-2.pptx
Industry 4.o the fourth revolutionWeek-2.pptx
KNaveenKumarECE
 
Proposal for folders structure division in projects.pdf
Proposal for folders structure division in projects.pdf
Mohamed Ahmed
 
IntroSlides-June-GDG-Cloud-Munich community [email protected]
IntroSlides-June-GDG-Cloud-Munich community [email protected]
Luiz Carneiro
 
David Boutry - Mentors Junior Developers
David Boutry - Mentors Junior Developers
David Boutry
 
machine learning is a advance technology
machine learning is a advance technology
ynancy893
 
最新版美国圣莫尼卡学院毕业证(SMC毕业证书)原版定制
最新版美国圣莫尼卡学院毕业证(SMC毕业证书)原版定制
Taqyea
 
International Journal of Advanced Information Technology (IJAIT)
International Journal of Advanced Information Technology (IJAIT)
ijait
 
Decoding Kotlin - Your Guide to Solving the Mysterious in Kotlin - Devoxx PL ...
Decoding Kotlin - Your Guide to Solving the Mysterious in Kotlin - Devoxx PL ...
João Esperancinha
 
FUNDAMENTALS OF COMPUTER ORGANIZATION AND ARCHITECTURE
FUNDAMENTALS OF COMPUTER ORGANIZATION AND ARCHITECTURE
Shabista Imam
 
System design handwritten notes guidance
System design handwritten notes guidance
Shabista Imam
 
NEW Strengthened Senior High School Gen Math.pptx
NEW Strengthened Senior High School Gen Math.pptx
DaryllWhere
 
Center Enamel can Provide Aluminum Dome Roofs for diesel tank.docx
Center Enamel can Provide Aluminum Dome Roofs for diesel tank.docx
CenterEnamel
 
special_edition_using_visual_foxpro_6.pdf
special_edition_using_visual_foxpro_6.pdf
Shabista Imam
 
Introduction to sensing and Week-1.pptx
Introduction to sensing and Week-1.pptx
KNaveenKumarECE
 
Machine Learning - Classification Algorithms
Machine Learning - Classification Algorithms
resming1
 
Learning – Types of Machine Learning – Supervised Learning – Unsupervised UNI...
Learning – Types of Machine Learning – Supervised Learning – Unsupervised UNI...
23Q95A6706
 
Fundamentals of Digital Design_Class_21st May - Copy.pptx
Fundamentals of Digital Design_Class_21st May - Copy.pptx
drdebarshi1993
 
Abraham Silberschatz-Operating System Concepts (9th,2012.12).pdf
Abraham Silberschatz-Operating System Concepts (9th,2012.12).pdf
Shabista Imam
 
Deep Learning for Natural Language Processing_FDP on 16 June 2025 MITS.pptx
Deep Learning for Natural Language Processing_FDP on 16 June 2025 MITS.pptx
resming1
 
Tesla-Stock-Analysis-and-Forecast.pptx (1).pptx
Tesla-Stock-Analysis-and-Forecast.pptx (1).pptx
moonsony54
 
Industry 4.o the fourth revolutionWeek-2.pptx
Industry 4.o the fourth revolutionWeek-2.pptx
KNaveenKumarECE
 
Proposal for folders structure division in projects.pdf
Proposal for folders structure division in projects.pdf
Mohamed Ahmed
 
David Boutry - Mentors Junior Developers
David Boutry - Mentors Junior Developers
David Boutry
 
machine learning is a advance technology
machine learning is a advance technology
ynancy893
 
最新版美国圣莫尼卡学院毕业证(SMC毕业证书)原版定制
最新版美国圣莫尼卡学院毕业证(SMC毕业证书)原版定制
Taqyea
 
International Journal of Advanced Information Technology (IJAIT)
International Journal of Advanced Information Technology (IJAIT)
ijait
 
Decoding Kotlin - Your Guide to Solving the Mysterious in Kotlin - Devoxx PL ...
Decoding Kotlin - Your Guide to Solving the Mysterious in Kotlin - Devoxx PL ...
João Esperancinha
 
FUNDAMENTALS OF COMPUTER ORGANIZATION AND ARCHITECTURE
FUNDAMENTALS OF COMPUTER ORGANIZATION AND ARCHITECTURE
Shabista Imam
 
System design handwritten notes guidance
System design handwritten notes guidance
Shabista Imam
 
NEW Strengthened Senior High School Gen Math.pptx
NEW Strengthened Senior High School Gen Math.pptx
DaryllWhere
 
Ad

Conquering JSONB in PostgreSQL

  • 2. Why did PostgreSQL add a JSON data type?
  • 3. Postgre SQL and NoSQL Postgre 9.4 (December 2014) JSONB: Binary format, slower input, faster processing JSON: Exact copy, same orderPostgre 9.2 No explicit schema Key-Value pairs in JSON are equal to Key-Value pairs in columns
  • 4. CREATE TABLE "PaymentRequest" ( "ID" bigint PRIMARY KEY NOT NULL, "Created" timestamp without time zone, "LastEdited" timestamp without time zone, "Identifier" character varying(50), "FinalPrice" double precision, ..., "DeliveryTypeJSON" jsonb, "DeliveryAddressJSON" jsonb, "InvoiceAddressJSON" jsonb, "PromotionCodeJSON" jsonb, "PaymentJSON" jsonb); CREATE TABLE "PaymentRequestEntry" ( "ID" bigint PRIMARY KEY NOT NULL, "CartCount" integer DEFAULT 0, "PriceWithTax" double precision, "FullPriceWithTax" double precision, "PriceNoTax" double precision, "FullPriceNoTax" double precision, ..., "ShopProductJSON" jsonb, "PaymentRequestID" integer DEFAULT 0, "VoucherID" integer DEFAULT 0 );
  • 5. class ShopProduct{ private function DataForInvoice() { $data = array( 'SKU' => $this->SKU, 'Title' => $this->LocaleTitle(), 'Variant' => $this->Variant, 'PriceWithTax' => $this->PriceWithTax(), 'PriceNoTax' => $this->PriceNoTax(), 'DiscountPriceWithTax'=> $this->PriceWithTax(true), 'DiscountPriceNoTax' => $this->PriceNoTax(true), 'Promotion' => $this->Promotion()->DataForInvoice(), 'TaxRate' => $this->TaxRate($nice = false), 'TaxPriceOfOne' => $this->TaxOfOneProduct(), 'NoTax' => $this->NoTax(), 'AllowOneStepTransaction' => $this->AllowOneStepTransaction, 'IsVoucher' => $this->IsVoucher, .... ); return $data; } }
  • 6. INSERT INTO "PaymentRequestEntry" VALUES ( 1, 21.60, 24.00, 17.70, 19.67, ..., '{ "SKU":"LJCRD-24-ADL", "Title": "Visit Ljubljana Card, 24 hours", "Variant": "Adult", "PriceWithTax": 24.00, "PriceNoTax": 19.67, ..., "Promotion": { "Code": "SUMMER17", "DiscountPercent": 10.00, "DiscountAmount": null, "ActiveFrom": "2017-05-15 00:00:00" "ActiveTo": "2017-06-15 00:00:00" } "TaxRate": 0.22 }', 845623 ); ERROR: invalid input syntax for type json
  • 7. "ShopProductJSON" ----------------------------------------------- { "SKU": "LJCRD-24-ADL", "NoTax": false, "Title": "Visit Ljubljana Card, 24 hours", "TaxRate": 0.22, "Variant": "Adult", "IsVoucher": false, "Promotion": { "Code": "SUMMER17", "ActiveTo": "2017-06-15 00:00:00", "ActiveFrom": "2017-05-15 00:00:00", "DiscountAmount": null, "DiscountPercent": "10.00" }, "PriceNoTax": 19.67, "TaxRateNice": 0.22, "PriceWithTax": 24.00, "DiscountPriceNoTax": 17.70, "DiscountPriceWithTax": 21.60, "AllowOneStepTransaction": 1, ... } SELECT "ShopProductJSON" FROM "PaymentRequestEntry" WHERE "ID" = 1
  • 9. select "ID", "WholePriceWithTax", "NumberOfItems", "ShopProductJSON"->>'SKU' AS "SKU", "ShopProductJSON"->>'Title' as "Title", "ShopProductJSON"->>'PriceWithTax' as "PriceWithTax", "ShopProductJSON" from "PaymentRequestEntry" WHERE "PaymentRequestID" = 1 ID WholePrice WithTax NumberOf Items SKU Title PriceWith Tax 1 21.6 1 LJCRD-24-ADL Visit Ljubljana Card, 2 4 hours 24 2 90 2 TOUR-BIKE-24 Bike tour of Ljubljana 45 3 387 2 WC-17 WebCamp 2017 15
  • 11. JSON Operators: -> arrays objects int text SELECT '["a",2,"3"]'::json->0 as data data (json) ------------------ "a" SELECT '["a",2,"3"]'::json->1 as data data (json) ------------------ 2 SELECT '["a",2,"3"]'::json->2 as data data (json) ------------------ "3" SELECT '["a",2,"3"]'::json->'a' as data data (json) ------------------ SELECT '{"a":1,"b":2}'::json->'b' as data data (json) ------------------ 2 SELECT '{"a":1,"b":{"c":[1,2]}}'::json->'b' data (json) ------------------ {"c":[1,2]} json json
  • 12. JSON Operators: ->> arrays int SELECT '["a",2,"3"]'::json->>0 as data data (text) ------------------ "a" SELECT '["a",2,"3"]'::json->>1 > 1 ERROR: operator does not exist: text > integer SELECT ('["a",2,"3"]'::json->>1)::int > 1 data (boolean) --------------- t SELECT ('["a",2,"3"]'::json->1)::int > 1 ERROR: cannot cast type json to integer text
  • 13. JSON Operators: ->> SELECT '{"a":1,"b":"word"}'::json->>'b' data (text) ------------------ "word" SELECT '{"a":1,"b":"word"}'::json->>'b' = 'word' data(boolean) ----------- t SELECT '{ "identifier":1mo3j4, "items":[ { "mon":"Monday", "tue":"Tuesday" }, { "jan":"january", "feb":"february" } ] }'::json->'items'->0->>'tue' data (text) -------------- "Tuesday" objects text text
  • 14. JSON Operators: #>, #>> SELECT '{ "id":1, "items":[ { "mon":"Monday", "tue":"Tuesday" }, { "jan":"january", "feb":"february" } ] }'::json #>> '{items,0,tue}' data (text) -------------- "Tuesday" SELECT '{ "id":1, "items":[ { "mon":"Monday", "tue":"Tuesday" }, { "jan":"january", "feb":"february" } ] }'::json ->'items'->0->>'tue' data (text) -------------- "Tuesday" objects array of text text
  • 15. JSONB Operators: @>, ? SELECT '{ "promotion": { "code":"SUMMER17", "discount":"10" } }'::jsonb ? 'promotion' SELECT '{ "promotion": { "code":"SUMMER17", "discount":"10" } }'::jsonb->'promotion' ? 'code' SELECT '{ "id":1, "promotion": { "code":"SUMMER17", "discount":"10" } }'::jsonb @> '{"promotion":{"code": "SUMMER17"}}' data (boolean) -------------- t objects text boolean objects jsonb boolean
  • 16. SELECT count("ID") as number_of_products_promo_was_used FROM "PaymentRequestEntry" WHERE "ShopProductJSON" @> '{"Promotion":{"Code": "SUMMER17"}}' { "SKU": "LJCRD-24-ADL", "IsVoucher": false, "Promotion": { "Code": "SUMMER17", }, "PriceNoTax": "19.67", "TaxRateNice": "0.22", "PriceWithTax": "24.00", "DiscountPriceNoTax": "10.00", "DiscountPriceWithTax": "10.00", } SELECT "PaymentRequestID", sum(("ShopProductJSON"->>'PriceWithTax')::float) - sum(("ShopProductJSON"->>'DiscountPriceWithTax')::float) as money_saved FROM "PaymentRequestEntry" WHERE "ShopProductJSON" @> '{"Promotion":{"Code": "SUMMER17"}}‘ GROUP BY "PaymentRequestID" PaymentRequestID money_saved 845623 5.12 845622 6.01 845625 2.2 ...
  • 17. SELECT SUM("CartCount") AS number_of_products, SUM(("ShopProductJSON"->>'PriceWithTax')::float) - SUM(("ShopProductJSON"->>'DiscountPriceWithTax')::float) AS money_saved, r."DeliveryAddressJSON"->>'Country' AS country FROM "PaymentRequestEntry" e INNER JOIN "PaymentRequest" r ON r."ID" = e."PaymentRequestID" WHERE "ShopProductJSON"->'Promotion'->>'Code' = 'SUMMER17' GROUP BY r."DeliveryAddressJSON"->>'Country' ORDER BY money_saved number_of_products money_saved country 481 1503.72 DE 512 1438.56 AT 503 1289.05 IT ...
  • 18. SELECT sp."CalculatedPrice", e."ShopProductJSON"->>'PriceWithTax' as bought_price, e."Created" FROM "PaymentRequestEntry" e INNER JOIN "ShopProduct" sp ON sp."SKU" = e."ShopProductJSON"->>'SKU' AND e."ShopProductJSON" @> '{"SKU": "LJCRD-24-ADL"}' ORDER BY e."Created" desc CalculatedPrice bought_price Created 24 24 2017-04-21 15:23:01 24 21.6 2017-04-21 15:22:12 ... 24 22 2016-12-01 07:17:53 ...
  • 19. EXPLAIN SELECT * FROM "PaymentRequestEntry" WHERE "ShopProductJSON" @> '{"Promotion":{"Code": "SUMMER17"}}' Seq Scan on "PaymentRequestEntry" (cost=0.00..21.02 rows=3 width=100) Filter: ((("ShopProductJSON" -> 'Promotion'::text) ->> 'Code'::text) = 'SUMMER17'::text) GIN index over the WHOLE JSON for only 1 key in the JSON jsonb_ops : bigger & more versatily jsonb_path_ops: smaller & supports only @> querys
  • 20. EXPLAIN SELECT * FROM "PaymentRequestEntry" WHERE "ShopProductJSON" @> '{"Promotion":{"Code": "SUMMER17"}}' Seq Scan on "PaymentRequestEntry" (cost=0.00..511091.51 rows=3662 width=85) table "PaymentRequestEntry" size: 3635 MB, 2.807.147 rows CREATE index json_index ON "PaymentRequestEntry" USING GIN (("ShopProductJSON"->'Promotion'->'Code')) CREATE index json_index ON "PaymentRequestEntry" USING GIN ("ShopProductJSON") @> <@ ? ?| ?& CREATE index json_index ON "PaymentRequestEntry" USING GIN ("ShopProductJSON" jsonb_path_ops) @> indexname num_rows index_size json_index_ops 2.807.147 10 MB json_index_path_ops 2.807.147 7.832 MB (-20%) json_index_column 2.807.147 3.112 MB (-70%) json_index_column_path 2.807.147 3.112 MB (-70%) 1. 2. 3.
  • 21. What have we used JSON data types for so far?
  • 24. JSON to Form { "type":"object", "title":"Comment", "properties":{ "name":{ "title":"Name", "type":"string" }, "email":{ "title":"Email", "type":"string", "pattern":"^S+@S+$", "description":"Email will be used for evil." }, "comment":{ "title":"Comment", "type":"string", "maxLength":20, "validationMessage":"Don't be greedy!" } }, "required":[ "name", "email", "comment" ] }