The Rise of JSON
in RDBMS land
hello!
I am Nicola Galgano
(@Alikon)
Real Time Application Management
2
JavaScript Object Notation
lightweight data
interchange format.
Easy for humans to
read and write.
easy for machines to
parse and generate.
3
Json value
Array and
object can
be nested
4
Relational DataBase Management System
✘Mysql
✘Postgresql
✘Sql Server
✘Oracle
✘DB2
5
Tuple
Tables
Attribute
PK
FK
Relational
Model
6
The statistics Plugin
7
The statistics API
{"php_version":
{"7.0":21.11,"5.6":39.77,"5.5":19.81},
"db_type":
{"mysqli“:79.5,"postgresql":19.09},
"cms_version":
{"3.7.0":8.97,"3.6.5":30.5,"3.6.0":6.71},
"server_os":{"Linux":73.16,"Windows":21.05}
,"total":8130468}
https://developer.joomla.org/stats 8
API Endpoint – GET /cms_version
0
10
20
30
40
50
60
70
cms
cms
3.7.x 9.53
3.6.x 61.06
3.5.x 29.25
9
Software development life cycle
THE BOSS
✘design software
that adapt to
future usage
✘No additional
programming.
10
DOCUMENT-ORIENTED
Think of documents
As rdbms records
Documents are
basically just json
object
11
…Show me your tables,
and I won't usually
need your flowchart;
it'll be obvious.
Fred Brooks
12
Ok fred, this is The stats Table
CREATE TABLE `#__jstats` (
`unique_id` INT NOT NULL,
`php_version` varchar(15) NOT NULL,
`db_type` varchar(15) NOT NULL,
`db_version` varchar(50) NOT NULL,
`cms_version` varchar(15) NOT NULL,
`server_os` varchar(255) NOT NULL,
PRIMARY KEY (`unique_id`))
13
Extend Table
CREATE TABLE `#__jstats` (
`unique_id` INT NOT NULL,
…
`extra_field1` varchar(50),
`extra_field2` varchar(50),
`extra_field3` varchar(50),
…
PRIMARY KEY (`unique_id`))
14
Good
No ALTER TABLE
Simple solution
For starting
Bad
More extra field:
again ALTER
TABLE
Columns lacks :
Descriptive name
data type
15
Entity Attribute Value Table
CREATE TABLE `#__jstats_attributes`
(`entity` INT NOT NULL,
`attribute` varchar(20) NOT NULL,
`value` TEXT,
FOREIGN KEY (`entity`)
REFERENCES `#__jstats` (`unique_id`)
)
16
Each attribute in a row instead of a column.
SELECT * FROM `#__jstats_attributes`;
+--------+------------------------+-------+
| entity | attribute | value |
+--------+-----------+------------+-------+
| 207468 | template | Picasso |
| 207468 | users | 130468 |
| 207468 | rating | 7.8 |
| 207468 | speed | 110 msec |
+--------+-----------------+------+-------+
17
How to Select all attribute in a row
+--------+----------+--------+--------+-------+
| entity | template | users | rating | speed |
+--------+----------+--------+--------+-------+
| 207468 | Picasso | 130468 | 7.8 | 110 |
+--------+----------+--------+--------+-------+
18
One Join per attribute
SELECT a.entity AS id,
a.value AS template
u.value AS users
r.value AS rating
s.value AS speed
FROM `#__jstats_attributes` AS a USING(entity)
JOIN `#__jstats_attributes` AS u USING(entity)
JOIN `#__jstats_attributes` AS r USING(entity)
JOIN `#__jstats_attributes` AS s USING(entity)
WHERE a.attribute = 'template'
AND u.attribute = 'users'
AND r.attribute = 'rating'
AND s.attribute = 'speed';
19
Good
✘no more
ALTER TABLE
✘Well “knowed”
solution
Bad
✘complex queries
✘NO constraints
✘Poor index
20
Linus Torvalds
…Bad programmers
worry about the code.
…Good programmers
worry about data
structures and their
relationships.
21
design your data better (1/3)
CREATE TABLE `#__jstats_components` (
…
`idc` INT NOT NULL,
`name` varchar(50),
`vendor` varchar(50),
`version` varchar(50),
…
FOREIGN KEY (`idc`)
REFERENCES `#__jstats` (`unique_id`) 22
design your data better (2/3)
CREATE TABLE `#__jstats_plugins` (
…
`idp` INT NOT NULL,
`name` varchar(50),
`vendor` varchar(50),
`version` varchar(50),
…
FOREIGN KEY (`idp`)
REFERENCES `#__jstats` (`unique_id`) 23
design your data better (3/3)
CREATE TABLE `#__jstats_templates` (
…
`idt` INT NOT NULL,
`name` varchar(50),
`vendor` varchar(50),
`version` varchar(50),
…
FOREIGN KEY (`idt`)
REFERENCES `#__jstats` (`unique_id`) 24
Pros
✘Just add TABLE
✘Easy to query
✘???
Cons
✘More tables
✘More code
✘???
25
Serialized LOB`
CREATE TABLE `#__assets`
(
`id` int(10) unsigned NOT
NULL AUTO_INCREMENT
…
`rules` varchar(5120) NOT
NULL COMMENT 'JSON encoded
access control',
…
PRIMARY KEY (`id`),
…
'{"core.login.site":{"6":1,"2":1},
"core.login.admin":{"6":1},
"core.login.offline":{"6":1},
"core.admin":{"8":1},
"core.manage":{"7":1},
"core.create":{"6":1,"3":1},
"core.delete":{"6":1},
"core.edit":{"6":1,"4":1},
"core.edit.state":{"6":1,"5":1},
"core.edit.own":{"6":1,"3":1}}'
26
Good
✘Store any object
✘add new custom
fields at any time
✘ ???
BAD
✘No indexable
✘Hard where
✘???
27
…Smart data
structures and dumb
code works a lot better
than the other way
around.
Eric S. Raymond
28
RDBMS with JSON Data Type
29
“MySQL and PostgreSQL
implementations mostly
intersect in extracting
elements but solve element
validation and manipulation
tasks in different ways.
30
A JSON COLUMN
CREATE TABLE #__names (data JSON);
INSERT INTO #__names VALUES ('{"id": 1, "name": “Nik"}');
INSERT INTO #__names VALUES ('{"id": 2, "name": "Joe"}');
SELECT data FROM #__names;
+---------------------------+
| data |
+---------------------------+
|{"id": 1, "name": “Nik"} |
|{"id": 2, "name": "Joe"} |
+---------------------------+
2 rows in set (0,00 sec)
31
The Json Values
mysql> SELECT CAST('{}' AS JSON) object
-> , CAST('[]' AS JSON) array
-> , CAST('null' AS JSON) "null"
-> , CAST('true' AS JSON) "true"
-> , CAST('false' AS JSON) "false"
-> , CAST('"string"' AS JSON) string
-> ;
+--------+-------+------+------+-------+----------+
| object | array | null | true | false | string |
+--------+-------+------+------+-------+----------+
| {} | [] | null | true | false | "string" |
+--------+-------+------+------+-------+----------+
32
The Json Data Type
SELECT JSON_TYPE(CAST('{}' AS JSON))
-> ,JSON_TYPE(CAST('""' AS JSON))
-> ,JSON_TYPE(CAST('true' AS JSON))
-> ,JSON_TYPE(CAST('null' AS JSON))
-> ,JSON_TYPE(CAST(1 AS JSON))
-> ,JSON_TYPE(CAST(1.1 AS JSON))
-> ,JSON_TYPE(CAST(PI() AS JSON))
-> ,JSON_TYPE(CAST(CURRENT_DATE AS JSON))
-> ,JSON_TYPE(CAST(CURRENT_TIME AS JSON))
-> ,JSON_TYPE(CAST('[]' AS JSON))
OBJECT
STRING
BOOLEAN
NULL
INTEGER
DECIMAL
DOUBLE
DATE
TIME
ARRAY
33
https://dev.mysql.com/doc/refman/5.7/en/json-functions.html
JSON Functions
34
JSON Array and Object
SELECT
JSON_ARRAY(1, 2, 3) array,
JSON_OBJECT(‘key1','value1',‘key2','value2') object;
+-----------+----------------------------------------+
| array | object |
+-----------+----------------------------------------+
| [1, 2, 3] | {“key1": "value1", “key2": "value2"} |
+-----------+----------------------------------------+
35
JSONPath
36
http://jsonpath.com
37
A JSON String
JSON_UNQUOTE(JSON_EXTRACT(mycol,"$.mypath"))
JSON_UNQUOTE(mycol->"$.mypath")
mycol->>"$.mypath"
38
JSON UNQUOTE/QUOTE
SELECT JSON_UNQUOTE(data->"$.name") AS unquoted_string
, JSON_EXTRACT(data,“$.name“) as quoted_string
, data->>"$.name“ as short
FROM #__jstats_templates
WHERE id = 1234;
+----------------+---------------+--------------------+
| unquoted_string| quoted_string | short |
+----------------+---------------+--------------------+
| Leonardo | “Leonardo“ | Leonardo |
+----------------+---------------+--------------------+
39
JSON FUNCTIONS
SELECT JSON_ARRAY(id, data->"$.name",
data->"$.version") AS json_array
FROM #__jstats_templates WHERE
JSON_EXTRACT(data,"$.vendor")=JSON_QUOTE("templater");
+-------------------------------+
| json_array |
+-------------------------------+
| [11298, "Picasso", "1.0.3"] |
| [12293, "Dalì", "2.3.1"] |
| [17284, "Leonardo", "1.1.8"] |
+-------------------------------+
40
JSON Replace
set @json = CAST('{"foo":"bar"}' AS JSON);
set @json =
JSON_REPLACE(@json,'$.foo',JSON_ARRAY('bar','car','far'))
mysql> SELECT @json;
+-------------------------------+
| @json |
+-------------------------------+
| '{"foo":["bar","car","far"]}' |
+-------------------------------+
41
Generated columns
Virtual (default)
✘will be calculated on the fly when a
record is read from a table
✘secondary indexes
✘No space
Stored
✘ will be calculated when a new
record is written in the table
✘indexing unique keys
✘Space required
column_name data_type [GENERATED ALWAYS] AS (expression)
[VIRTUAL | STORED] [UNIQUE [KEY]]
42
Index JSON
CREATE TABLE #__jstats_templates (
`id` int(11) NOT NULL AUTO_INCREMENT,
`data` json NOT NULL,
`vendor` varchar(30) GENERATED ALWAYS
AS(data->>"$.vendor") VIRTUAL,
PRIMARY KEY (id),
KEY ix_vendor (vendor)
) ENGINE=InnoDB
43
44
The GOOD
✘same reasons as you decide to use MongoDB
✘Dynamic structure
✘Faster for developers to implement changes
✘Migration opportunities
45
The Bad & Ugly
✘Learning curve
✘No standard
✘???
46
Confused?

The rise of json in rdbms land jab17

  • 1.
    The Rise ofJSON in RDBMS land
  • 2.
    hello! I am NicolaGalgano (@Alikon) Real Time Application Management 2
  • 3.
    JavaScript Object Notation lightweightdata interchange format. Easy for humans to read and write. easy for machines to parse and generate. 3
  • 4.
  • 5.
    Relational DataBase ManagementSystem ✘Mysql ✘Postgresql ✘Sql Server ✘Oracle ✘DB2 5
  • 6.
  • 7.
  • 8.
  • 9.
    API Endpoint –GET /cms_version 0 10 20 30 40 50 60 70 cms cms 3.7.x 9.53 3.6.x 61.06 3.5.x 29.25 9
  • 10.
    Software development lifecycle THE BOSS ✘design software that adapt to future usage ✘No additional programming. 10
  • 11.
    DOCUMENT-ORIENTED Think of documents Asrdbms records Documents are basically just json object 11
  • 12.
    …Show me yourtables, and I won't usually need your flowchart; it'll be obvious. Fred Brooks 12
  • 13.
    Ok fred, thisis The stats Table CREATE TABLE `#__jstats` ( `unique_id` INT NOT NULL, `php_version` varchar(15) NOT NULL, `db_type` varchar(15) NOT NULL, `db_version` varchar(50) NOT NULL, `cms_version` varchar(15) NOT NULL, `server_os` varchar(255) NOT NULL, PRIMARY KEY (`unique_id`)) 13
  • 14.
    Extend Table CREATE TABLE`#__jstats` ( `unique_id` INT NOT NULL, … `extra_field1` varchar(50), `extra_field2` varchar(50), `extra_field3` varchar(50), … PRIMARY KEY (`unique_id`)) 14
  • 15.
    Good No ALTER TABLE Simplesolution For starting Bad More extra field: again ALTER TABLE Columns lacks : Descriptive name data type 15
  • 16.
    Entity Attribute ValueTable CREATE TABLE `#__jstats_attributes` (`entity` INT NOT NULL, `attribute` varchar(20) NOT NULL, `value` TEXT, FOREIGN KEY (`entity`) REFERENCES `#__jstats` (`unique_id`) ) 16
  • 17.
    Each attribute ina row instead of a column. SELECT * FROM `#__jstats_attributes`; +--------+------------------------+-------+ | entity | attribute | value | +--------+-----------+------------+-------+ | 207468 | template | Picasso | | 207468 | users | 130468 | | 207468 | rating | 7.8 | | 207468 | speed | 110 msec | +--------+-----------------+------+-------+ 17
  • 18.
    How to Selectall attribute in a row +--------+----------+--------+--------+-------+ | entity | template | users | rating | speed | +--------+----------+--------+--------+-------+ | 207468 | Picasso | 130468 | 7.8 | 110 | +--------+----------+--------+--------+-------+ 18
  • 19.
    One Join perattribute SELECT a.entity AS id, a.value AS template u.value AS users r.value AS rating s.value AS speed FROM `#__jstats_attributes` AS a USING(entity) JOIN `#__jstats_attributes` AS u USING(entity) JOIN `#__jstats_attributes` AS r USING(entity) JOIN `#__jstats_attributes` AS s USING(entity) WHERE a.attribute = 'template' AND u.attribute = 'users' AND r.attribute = 'rating' AND s.attribute = 'speed'; 19
  • 20.
    Good ✘no more ALTER TABLE ✘Well“knowed” solution Bad ✘complex queries ✘NO constraints ✘Poor index 20
  • 21.
    Linus Torvalds …Bad programmers worryabout the code. …Good programmers worry about data structures and their relationships. 21
  • 22.
    design your databetter (1/3) CREATE TABLE `#__jstats_components` ( … `idc` INT NOT NULL, `name` varchar(50), `vendor` varchar(50), `version` varchar(50), … FOREIGN KEY (`idc`) REFERENCES `#__jstats` (`unique_id`) 22
  • 23.
    design your databetter (2/3) CREATE TABLE `#__jstats_plugins` ( … `idp` INT NOT NULL, `name` varchar(50), `vendor` varchar(50), `version` varchar(50), … FOREIGN KEY (`idp`) REFERENCES `#__jstats` (`unique_id`) 23
  • 24.
    design your databetter (3/3) CREATE TABLE `#__jstats_templates` ( … `idt` INT NOT NULL, `name` varchar(50), `vendor` varchar(50), `version` varchar(50), … FOREIGN KEY (`idt`) REFERENCES `#__jstats` (`unique_id`) 24
  • 25.
    Pros ✘Just add TABLE ✘Easyto query ✘??? Cons ✘More tables ✘More code ✘??? 25
  • 26.
    Serialized LOB` CREATE TABLE`#__assets` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT … `rules` varchar(5120) NOT NULL COMMENT 'JSON encoded access control', … PRIMARY KEY (`id`), … '{"core.login.site":{"6":1,"2":1}, "core.login.admin":{"6":1}, "core.login.offline":{"6":1}, "core.admin":{"8":1}, "core.manage":{"7":1}, "core.create":{"6":1,"3":1}, "core.delete":{"6":1}, "core.edit":{"6":1,"4":1}, "core.edit.state":{"6":1,"5":1}, "core.edit.own":{"6":1,"3":1}}' 26
  • 27.
    Good ✘Store any object ✘addnew custom fields at any time ✘ ??? BAD ✘No indexable ✘Hard where ✘??? 27
  • 28.
    …Smart data structures anddumb code works a lot better than the other way around. Eric S. Raymond 28
  • 29.
    RDBMS with JSONData Type 29
  • 30.
    “MySQL and PostgreSQL implementationsmostly intersect in extracting elements but solve element validation and manipulation tasks in different ways. 30
  • 31.
    A JSON COLUMN CREATETABLE #__names (data JSON); INSERT INTO #__names VALUES ('{"id": 1, "name": “Nik"}'); INSERT INTO #__names VALUES ('{"id": 2, "name": "Joe"}'); SELECT data FROM #__names; +---------------------------+ | data | +---------------------------+ |{"id": 1, "name": “Nik"} | |{"id": 2, "name": "Joe"} | +---------------------------+ 2 rows in set (0,00 sec) 31
  • 32.
    The Json Values mysql>SELECT CAST('{}' AS JSON) object -> , CAST('[]' AS JSON) array -> , CAST('null' AS JSON) "null" -> , CAST('true' AS JSON) "true" -> , CAST('false' AS JSON) "false" -> , CAST('"string"' AS JSON) string -> ; +--------+-------+------+------+-------+----------+ | object | array | null | true | false | string | +--------+-------+------+------+-------+----------+ | {} | [] | null | true | false | "string" | +--------+-------+------+------+-------+----------+ 32
  • 33.
    The Json DataType SELECT JSON_TYPE(CAST('{}' AS JSON)) -> ,JSON_TYPE(CAST('""' AS JSON)) -> ,JSON_TYPE(CAST('true' AS JSON)) -> ,JSON_TYPE(CAST('null' AS JSON)) -> ,JSON_TYPE(CAST(1 AS JSON)) -> ,JSON_TYPE(CAST(1.1 AS JSON)) -> ,JSON_TYPE(CAST(PI() AS JSON)) -> ,JSON_TYPE(CAST(CURRENT_DATE AS JSON)) -> ,JSON_TYPE(CAST(CURRENT_TIME AS JSON)) -> ,JSON_TYPE(CAST('[]' AS JSON)) OBJECT STRING BOOLEAN NULL INTEGER DECIMAL DOUBLE DATE TIME ARRAY 33
  • 34.
  • 35.
    JSON Array andObject SELECT JSON_ARRAY(1, 2, 3) array, JSON_OBJECT(‘key1','value1',‘key2','value2') object; +-----------+----------------------------------------+ | array | object | +-----------+----------------------------------------+ | [1, 2, 3] | {“key1": "value1", “key2": "value2"} | +-----------+----------------------------------------+ 35
  • 36.
  • 37.
  • 38.
  • 39.
    JSON UNQUOTE/QUOTE SELECT JSON_UNQUOTE(data->"$.name")AS unquoted_string , JSON_EXTRACT(data,“$.name“) as quoted_string , data->>"$.name“ as short FROM #__jstats_templates WHERE id = 1234; +----------------+---------------+--------------------+ | unquoted_string| quoted_string | short | +----------------+---------------+--------------------+ | Leonardo | “Leonardo“ | Leonardo | +----------------+---------------+--------------------+ 39
  • 40.
    JSON FUNCTIONS SELECT JSON_ARRAY(id,data->"$.name", data->"$.version") AS json_array FROM #__jstats_templates WHERE JSON_EXTRACT(data,"$.vendor")=JSON_QUOTE("templater"); +-------------------------------+ | json_array | +-------------------------------+ | [11298, "Picasso", "1.0.3"] | | [12293, "Dalì", "2.3.1"] | | [17284, "Leonardo", "1.1.8"] | +-------------------------------+ 40
  • 41.
    JSON Replace set @json= CAST('{"foo":"bar"}' AS JSON); set @json = JSON_REPLACE(@json,'$.foo',JSON_ARRAY('bar','car','far')) mysql> SELECT @json; +-------------------------------+ | @json | +-------------------------------+ | '{"foo":["bar","car","far"]}' | +-------------------------------+ 41
  • 42.
    Generated columns Virtual (default) ✘willbe calculated on the fly when a record is read from a table ✘secondary indexes ✘No space Stored ✘ will be calculated when a new record is written in the table ✘indexing unique keys ✘Space required column_name data_type [GENERATED ALWAYS] AS (expression) [VIRTUAL | STORED] [UNIQUE [KEY]] 42
  • 43.
    Index JSON CREATE TABLE#__jstats_templates ( `id` int(11) NOT NULL AUTO_INCREMENT, `data` json NOT NULL, `vendor` varchar(30) GENERATED ALWAYS AS(data->>"$.vendor") VIRTUAL, PRIMARY KEY (id), KEY ix_vendor (vendor) ) ENGINE=InnoDB 43
  • 44.
  • 45.
    The GOOD ✘same reasonsas you decide to use MongoDB ✘Dynamic structure ✘Faster for developers to implement changes ✘Migration opportunities 45
  • 46.
    The Bad &Ugly ✘Learning curve ✘No standard ✘??? 46
  • 47.