SlideShare a Scribd company logo
{ JSON }
in MySQL and MariaDB
Databases
Federico Razzoli
€ whoami
● Federico Razzoli
● Freelance consultant
● Working with databases since 2000
hello@federico-razzoli.com
federico-razzoli.com
● I worked as a consultant for Percona and Ibuildings
(mainly MySQL and MariaDB)
● I worked as a DBA for fast-growing companies like
Catawiki, HumanState, TransferWise
JSON Support
JSON Support
● MySQL 7.0 has a JSON type and JSON functions
● MariaDB 10.2 has JSON alias (LONGTEXT) and JSON functions
○ From MariaDB 10.4 JSON columns must contain valid JSON data
JSON Type Benefits
● Persons from both MySQL and MariaDB state that their approach is faster
○ Surprise, surprise!
● MySQL format is smaller
● When updating a property, MySQL does not rewrite the whole JSON
document
● MySQL binary log only contains the modified properties
○ binlog_row_value_options = 'PARTIAL_JSON'
● However, in MySQL 8, make sure that:
○ Default_tmp_storage_engine = 'TEMPTABLE'
JSON Features Comparison
● Let’s compare JSON features, and more generic features that are useful
working with JSON
● MySQL 8.0 / MariaDB 10.5
● MySQL only:
○ Index arrays (requires multi-valued indexes)
○ Schema validation
○ JSON_TABLE()
○ Functional index / Index on VIRTUAL column
● MariaDB only:
○ CONNECT (use a JSON file as a table)
○ Stored aggregate functions
Use Cases
JSON in relational databases?
● Relational databases are schemaful
● All rows must have the same columns (name, type)
○ (though NULL is often use to relax the schema)
● CHECK constraints:
○ email VARCHAR(100) CHECK (email LIKE '_%@_%._%')
○ birth_date DATE, death_date DATE, CHECK (birth_date <= death_date)
● UNIQUE constraint
● Referential constraints (foreign keys):
○ Each row in a child table matches a row in a parent table
JSON in relational databases?
● JSON is usually schemaless
● Two different objects can have different structures:
{
"product-type": "shirt",
"cost": 10.0,
"size": "M"
}
{
"product-type": "phone",
"cost": 69.99,
"size": [6.37, 2.9, 0.3],
"os": "Android"
}
JSON in relational databases?
● How would you store heterogeneous products in a relational database?
JSON in relational databases?
● How would you store heterogeneous products in a relational database?
● One table per product type?
○ Cannot enforce UNIQUE constraint
○ Try to find a product that could be of any type…
○ Try to get the min and max costs...
JSON in relational databases?
● How would you store heterogeneous products in a relational database?
● One table with one column for each property, NULL where it is not used?
○ Adding a product implies a slow, painful ALTER TABLE
○ If products type is deleted, obsolete columns tend to remain forever
○ Big table is bad for operations (backup, repair…)
○ INSERTs are slow
○ SELECT *
JSON in relational databases?
● How would you store heterogeneous products in a relational database?
● One main table with common properties, and one separate table for each
product type?
○ You can now see min/max costs, or find a product of any type
○ Many JOINs
JSON in relational databases?
● How would you store heterogeneous products in a relational database?
● Entity-Attribute-Value pattern (EAV)?
○ Store all data as texts
○ Crazy amount of JOINs
JSON in relational databases?
● How would you store heterogeneous products in a relational database?
● Single table, where all non-common property are stored as JSON
○ Still not perfect
○ But it’s good enough
JSON in relational databases?
CREATE TABLE product (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
type VARCHAR(50) NOT NULL,
name VARCHAR(50) NOT NULL,
cost DECIMAL(10, 2) NOT NULL,
quantity INT UNSIGNED NOT NULL,
attributes JSON NOT NULL
);
Indexing Properties
Materialising Properties
CREATE TABLE product (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
type VARCHAR(50),
name VARCHAR(50) NOT NULL,
cost DECIMAL(10, 2) NOT NULL,
quantity INT UNSIGNED NOT NULL,
attributes JSON NOT NULL,
colour VARCHAR(50) AS
(JSON_UNQUOTE(
JSON_EXTRACT(attributes, '$.colour')
)) STORED
);
MySQL shortcut
CREATE TABLE product (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
type VARCHAR(50),
name VARCHAR(50) NOT NULL,
cost DECIMAL(10, 2) NOT NULL,
quantity INT UNSIGNED NOT NULL,
attributes JSON NOT NULL,
colour VARCHAR(50) AS
(attributes->>'$.colour') VIRTUAL
);
Index on a Property
CREATE TABLE product (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
type VARCHAR(50),
name VARCHAR(50) NOT NULL,
cost DECIMAL(10, 2) NOT NULL,
quantity INT UNSIGNED NOT NULL,
attributes JSON NOT NULL,
colour VARCHAR(50) AS
(attributes->>'$.colour') VIRTUAL,
INDEX idx_colour (type, colour)
);
Index on a Property
SELECT id FROM product
WHERE type = 'FURNITURE'
AND colour = 'grey'
;
-- only uses the index in MySQL
SELECT id FROM product
WHERE type = 'FURNITURE'
AND attributes->>'$.colour' = 'grey'
;
Indexing Properties
CREATE TABLE product (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
type VARCHAR(50),
name VARCHAR(50) NOT NULL,
cost DECIMAL(10, 2) NOT NULL,
quantity INT UNSIGNED NOT NULL,
attributes JSON NOT NULL,
furniture_colour VARCHAR(50) AS
(IF(type = 'FURNITURE',
attributes->>'$.colour',
NULL
)) VIRTUAL,
INDEX idx_colour (furniture_colour)
Indexing Arrays
Indexing ARRAYS
● MySQL and MariaDB historically don’t support arrays
● Now they can use JSON arrays as “regular” arrays
● MySQL 8.0 supports Multi-Valued Indexes, that allow to index these arrays
○ Can be used to index JSON objects, not covered here
Indexing Arrays
CREATE TABLE `order` (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
customer_id INT UNSIGNED NOT NULL,
product_ids JSON NOT NULL,
INDEX idx_products (
(CAST(product_ids AS UNSIGNED ARRAY))
)
);
INSERT INTO `order` (customer_id, product_ids) VALUES
(24, JSON_ARRAY(10, 20, 30));
Indexing Arrays
SELECT DISTINCT customer_id
FROM `order`
WHERE 20 MEMBER OF (product_ids);
● JSON_CONTAINS()
● JSON_OVERLAPS()
Relationships
Foreign Keys on Properties
CREATE TABLE product (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
type VARCHAR(50),
...
furniture_colour INT UNSIGNED AS
(IF(type = 'FURNITURE',
attributes->>'$.colour',
NULL
)) STORED,
INDEX idx_furniture_colour (furniture_colour),
FOREIGN KEY fk_furniture_colour (furniture_colour)
REFERENCES furniture_colour (id)
);
Not suggesting to use Foreign Keys
● They come with several penalties
○ Slower writes
○ Propagated locks (for CASCADE FKs)
○ Limitations (only InnoDB, no partitions)
○ Cannot run safe online migrations
● Google for:
Federico Razzoli "Foreign Key bugs in MySQL and MariaDB"
But...
● But you can do the same without foreign keys
● You can easily add extra columns to furniture_colour
● You don’t have to mind about colour name details (case, extra spaces…)
● You can easily change a colour name
● You keep the JSON documents smaller
Basically, you can use the relational databases philosophy
While keeping some semi-structured data inside them
Validating JSON documents
Validating Against a JSON Schema
● Both MySQL and MariaDB only accept valid JSON documents in JSON
columns
● The CHECK clause defines the rules that determine if a row is valid
● JSON_SCHEMA_VALID() in MySQL validates a JSON document against a
JSON Schema
○ json-schema.org
○ Draft 4
○ But from my tests we can use drafts 6 or 7
Validating Schema
SELECT JSON_SCHEMA_VALID(@schema, @document);
SELECT JSON_SCHEMA_VALID((
SELECT schema
FROM schemas
WHERE type = 'furniture'
), document)
FROM product
WHERE id = 24
;
Validating Schema
Suppose we want to validate objects of this type:
{
"material": "iron",
"colour": "grey",
"size": [1.5, 1.5, 1.0]
}
{
"$id": "https://federico-razzoli.com/schemas/furniture",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"material": {
"type": "string",
"enum": ["iron", "wood"]
},
"size": {
"type": "array",
"items": {
"type": "number",
"minItems": 3,
"maxItems": 3
}
},
"colour": {
"type": "string"
}
},
"required": ["material", "size"]
}
Debugging a JSON Schema
● SELECT JSON_SCHEMA_VALID() + SHOW WARNINGS
● JSON_SCHEMA_VALIDATION_REPORT()
Default Properties
Default Properties
● We can have a JSON document with the default properties
● And only store non-default values in each regular JSON document
● This is useful:
○ For large JSON objects (eg. software configuration)
○ For objects whose defaults may change (eg. software whose settings can
be set per user and per team)
Merging Documents
-- get user settings
SET @user_conf := (
SELECT json_settings FROM user_configuration
WHERE id = 24
);
-- get team settings
SET @team_conf := (
SELECT json_settings FROM team_configuration
WHERE id = 123
);
-- merge them. user settings overwrite team settings
SELECT JSON_MERGE_PATCH(@team_conf, @user_conf);
JSON_MERGE_PATCH() example
mysql> SELECT JSON_MERGE_PATCH(
'{"items-per-page": 24, "suppress_warnings": true}',
'{"suppress_warnings": false}')
AS configuration;
+----------------------------------------------------+
| configuration |
+----------------------------------------------------+
| {"items-per-page": 24, "suppress_warnings": false} |
+----------------------------------------------------+
JSON_ARRAYAGG()
JSON_OBJECTAGG()
JSON_ARRAYAGG(),
JSON_OBJECTAGG()
● Available in:
○ MySQL 5.7
○ MariaDB 10.5, currently not GA
● However, they are:
○ Simple to emulate with GROUP_CONCAT()
○ Easy to code with MariaDB Stored Aggregate Functions (10.3)
JSON_ARRAYAGG()
mysql> SELECT type, JSON_ARRAYAGG(colour) AS colours
-> FROM product
-> GROUP BY type
-> ORDER BY type;
+-------+-----------------------------------+
| type | colours |
+-------+-----------------------------------+
| chair | ["green", "blue", "red", "black"] |
| shelf | ["white", "brown"] |
| table | ["white", "gray", "black"] |
+-------+-----------------------------------+
JSON_OBJECTAGG(): one document
mysql> SELECT
-> JSON_PRETTY(
-> JSON_OBJECTAGG(variable, value)
-> ) AS settings
-> FROM config G
*************************** 1. row ***************************
settings: {
"datadir": "/var/mysql/data",
"log_bin": "1",
"general_log": "0",
"slow_query_log": "0",
"innodb_log_file_size": "1G",
"innodb_log_buffer_size": "16M",
"innodb_buffer_pool_size": "16G"
}
JSON_OBJECTAGG()
nested objects
mysql> SELECT
-> JSON_PRETTY(
-> JSON_OBJECTAGG(
-> variable,
-> JSON_OBJECT(
-> 'type', type,
-> 'value', value
-> )
-> )
-> ) AS settings
-> FROM config;
JSON_OBJECTAGG()
nested objects
settings: {
"datadir": {
"type": "string",
"value": "/var/mysql/data"
},
"log_bin": {
"type": "bool",
"value": "1"
},
...
}
JSON_OBJECTAGG():
one document per row
mysql> SELECT JSON_OBJECTAGG(variable, value) AS settings
-> FROM config
-> GROUP BY variable;
+------------------------------------+
| settings |
+------------------------------------+
| {"datadir": "/var/mysql/data"} |
| {"general_log": "0"} |
| {"innodb_buffer_pool_size": "16G"} |
| {"innodb_log_buffer_size": "16M"} |
| {"innodb_log_file_size": "1G"} |
| {"log_bin": "1"} |
| {"slow_query_log": "0"} |
+------------------------------------+
JSON_TABLE()
JSON_TABLE()
● Only MySQL 8
● Transforms a JSON document into a table
● Each property, or some properties, become a table column
● Properties are identified by JSON Path expressions
JSON_TABLE() example
{
"customers": [
{
"name": "John Doe",
"emails": ["john@doe.com"],
"phone": "123456"
},
{
"name": "Jane Dee",
"emails": ["Jane@dee.com"],
"phone": "987654"
},
{
"name": "Donald Duck",
"emails": []
}
],
"products": [],
"orders": []
}
JSON_TABLE() example
SELECT *
FROM JSON_TABLE(
@customers,
'$.customers[*]'
COLUMNS (
id FOR ORDINALITY,
name VARCHAR(50) PATH '$.name',
primary_email VARCHAR(50) PATH '$.emails[0]',
phone VARCHAR(50) PATH '$.phone'
DEFAULT '"UNKNOWN"' ON EMPTY
NULL ON ERROR
)
) AS customers;
JSON_TABLE() example
+------+-------------+---------------+---------+
| id | name | primary_email | phone |
+------+-------------+---------------+---------+
| 1 | John Doe | john@doe.com | 123456 |
| 2 | Jane Dee | Jane@dee.com | 987654 |
| 3 | Donald Duck | NULL | UNKNOWN |
+------+-------------+---------------+---------+
MariaDB CONNECT
What CONNECT is
● Connect is a storage engine for MariaDB
○ Won’t compile on MySQL or Percona Server
● Reads data from different data sources:
○ Remote tables (MySQL protocol, ODBC, JDBC)
○ Files in various formats (JSON, XML, CSV, custom formats…)
○ Special data sources
○ Transformed data from other tables (pivot, …)
CONNECT and JSON
● JSON Table Type (10.1)
● On Windows, can read data from REST APIs (not easy to do)
● CONNECT comes with a library of JSON UDFs
○ Probably not battle-tested as the current built-in functions
Thank you for listening!
Federico
hello@federico-razzoli.com

More Related Content

What's hot (14)

PDF
Modern Application Foundations: Underscore and Twitter Bootstrap
Howard Lewis Ship
 
PDF
Embedding a language into string interpolator
Michael Limansky
 
PPTX
Service Oriented Architecture-Unit-1-XML Schema
Ramco Institute of Technology, Rajapalayam, Tamilnadu, India
 
PDF
Advanced MongoDB #1
Takahiro Inoue
 
PDF
DataMapper @ RubyEnRails2009
Dirkjan Bussink
 
PDF
Hands on JSON
Octavian Nadolu
 
DOCX
SQL & PLSQL
Prakash Poudel
 
PDF
Improving RDF Search Performance with Lucene and SIREN
Mike Hugo
 
PDF
mondrian-olap JRuby library
Raimonds Simanovskis
 
PDF
Modeling for Performance
MongoDB
 
PDF
Data Modeling for Performance
Michael Dwan
 
PPT
Propel sfugmd
iKlaus
 
PDF
Sql commands
Christalin Nelson
 
PDF
Hibernate
Leonardo Passos
 
Modern Application Foundations: Underscore and Twitter Bootstrap
Howard Lewis Ship
 
Embedding a language into string interpolator
Michael Limansky
 
Service Oriented Architecture-Unit-1-XML Schema
Ramco Institute of Technology, Rajapalayam, Tamilnadu, India
 
Advanced MongoDB #1
Takahiro Inoue
 
DataMapper @ RubyEnRails2009
Dirkjan Bussink
 
Hands on JSON
Octavian Nadolu
 
SQL & PLSQL
Prakash Poudel
 
Improving RDF Search Performance with Lucene and SIREN
Mike Hugo
 
mondrian-olap JRuby library
Raimonds Simanovskis
 
Modeling for Performance
MongoDB
 
Data Modeling for Performance
Michael Dwan
 
Propel sfugmd
iKlaus
 
Sql commands
Christalin Nelson
 
Hibernate
Leonardo Passos
 

Similar to JSON in MySQL and MariaDB Databases (20)

PDF
Moving to hybrid relational/JSON data models
MariaDB plc
 
PDF
Using semi-structured data in modern applications
MariaDB plc
 
PDF
Hybrid Data Models - Relational + JSON
DATAVERSITY
 
PDF
Hyrbid Data Models (relational + json)
MariaDB plc
 
PPTX
Somewhere between schema and schemaless
MariaDB plc
 
PDF
M|18 Somewhere Between Schema and Schemaless
MariaDB plc
 
PDF
Hybrid Databases - PHP UK Conference 22 February 2019
Dave Stokes
 
PPTX
The rise of json in rdbms land jab17
alikonweb
 
PDF
Wie man Datenbankinfrastrukturen in Containern zum Laufen bringt
MariaDB plc
 
PDF
How to Handle NoSQL with a Relational Database
DATAVERSITY
 
PPTX
Php forum2015 tomas_final
Bertrand Matthelie
 
PDF
MySQL 5.7 + JSON
Morgan Tocker
 
PDF
Json improvements in my sql 8.0
Mysql User Camp
 
PPTX
JSON improvements in MySQL 8.0
Mydbops
 
PDF
MySQL 5.7. Tutorial - Dutch PHP Conference 2015
Dave Stokes
 
PDF
MySQL 5.7 Tutorial Dutch PHP Conference 2015
Dave Stokes
 
PDF
Optimizer percona live_ams2015
Manyi Lu
 
PDF
5_MariaDB_What's New in MariaDB Server 10.2 and Big Data Analytics with Maria...
Kangaroot
 
PDF
MySQL 8.0.17 - New Features Summary
Olivier DASINI
 
PDF
How to Use JSON in MySQL Wrong
Karwin Software Solutions LLC
 
Moving to hybrid relational/JSON data models
MariaDB plc
 
Using semi-structured data in modern applications
MariaDB plc
 
Hybrid Data Models - Relational + JSON
DATAVERSITY
 
Hyrbid Data Models (relational + json)
MariaDB plc
 
Somewhere between schema and schemaless
MariaDB plc
 
M|18 Somewhere Between Schema and Schemaless
MariaDB plc
 
Hybrid Databases - PHP UK Conference 22 February 2019
Dave Stokes
 
The rise of json in rdbms land jab17
alikonweb
 
Wie man Datenbankinfrastrukturen in Containern zum Laufen bringt
MariaDB plc
 
How to Handle NoSQL with a Relational Database
DATAVERSITY
 
Php forum2015 tomas_final
Bertrand Matthelie
 
MySQL 5.7 + JSON
Morgan Tocker
 
Json improvements in my sql 8.0
Mysql User Camp
 
JSON improvements in MySQL 8.0
Mydbops
 
MySQL 5.7. Tutorial - Dutch PHP Conference 2015
Dave Stokes
 
MySQL 5.7 Tutorial Dutch PHP Conference 2015
Dave Stokes
 
Optimizer percona live_ams2015
Manyi Lu
 
5_MariaDB_What's New in MariaDB Server 10.2 and Big Data Analytics with Maria...
Kangaroot
 
MySQL 8.0.17 - New Features Summary
Olivier DASINI
 
How to Use JSON in MySQL Wrong
Karwin Software Solutions LLC
 
Ad

More from Federico Razzoli (20)

PDF
MariaDB Data Protection: Backup Strategies for the Real World
Federico Razzoli
 
PDF
MariaDB/MySQL_: Developing Scalable Applications
Federico Razzoli
 
PDF
Webinar: Designing a schema for a Data Warehouse
Federico Razzoli
 
PDF
High-level architecture of a complete MariaDB deployment
Federico Razzoli
 
PDF
Webinar - Unleash AI power with MySQL and MindsDB
Federico Razzoli
 
PDF
MariaDB Security Best Practices
Federico Razzoli
 
PDF
A first look at MariaDB 11.x features and ideas on how to use them
Federico Razzoli
 
PDF
MariaDB stored procedures and why they should be improved
Federico Razzoli
 
PDF
Webinar - MariaDB Temporal Tables: a demonstration
Federico Razzoli
 
PDF
Webinar - Key Reasons to Upgrade to MySQL 8.0 or MariaDB 10.11
Federico Razzoli
 
PDF
MariaDB 10.11 key features overview for DBAs
Federico Razzoli
 
PDF
Recent MariaDB features to learn for a happy life
Federico Razzoli
 
PDF
Advanced MariaDB features that developers love.pdf
Federico Razzoli
 
PDF
Automate MariaDB Galera clusters deployments with Ansible
Federico Razzoli
 
PDF
Creating Vagrant development machines with MariaDB
Federico Razzoli
 
PDF
MariaDB, MySQL and Ansible: automating database infrastructures
Federico Razzoli
 
PDF
Playing with the CONNECT storage engine
Federico Razzoli
 
PDF
MariaDB Temporal Tables
Federico Razzoli
 
PDF
Database Design most common pitfalls
Federico Razzoli
 
PDF
MySQL and MariaDB Backups
Federico Razzoli
 
MariaDB Data Protection: Backup Strategies for the Real World
Federico Razzoli
 
MariaDB/MySQL_: Developing Scalable Applications
Federico Razzoli
 
Webinar: Designing a schema for a Data Warehouse
Federico Razzoli
 
High-level architecture of a complete MariaDB deployment
Federico Razzoli
 
Webinar - Unleash AI power with MySQL and MindsDB
Federico Razzoli
 
MariaDB Security Best Practices
Federico Razzoli
 
A first look at MariaDB 11.x features and ideas on how to use them
Federico Razzoli
 
MariaDB stored procedures and why they should be improved
Federico Razzoli
 
Webinar - MariaDB Temporal Tables: a demonstration
Federico Razzoli
 
Webinar - Key Reasons to Upgrade to MySQL 8.0 or MariaDB 10.11
Federico Razzoli
 
MariaDB 10.11 key features overview for DBAs
Federico Razzoli
 
Recent MariaDB features to learn for a happy life
Federico Razzoli
 
Advanced MariaDB features that developers love.pdf
Federico Razzoli
 
Automate MariaDB Galera clusters deployments with Ansible
Federico Razzoli
 
Creating Vagrant development machines with MariaDB
Federico Razzoli
 
MariaDB, MySQL and Ansible: automating database infrastructures
Federico Razzoli
 
Playing with the CONNECT storage engine
Federico Razzoli
 
MariaDB Temporal Tables
Federico Razzoli
 
Database Design most common pitfalls
Federico Razzoli
 
MySQL and MariaDB Backups
Federico Razzoli
 
Ad

Recently uploaded (20)

PDF
4K Video Downloader Plus Pro Crack for MacOS New Download 2025
bashirkhan333g
 
PDF
HiHelloHR – Simplify HR Operations for Modern Workplaces
HiHelloHR
 
PDF
Digger Solo: Semantic search and maps for your local files
seanpedersen96
 
PDF
iTop VPN With Crack Lifetime Activation Key-CODE
utfefguu
 
PDF
Empower Your Tech Vision- Why Businesses Prefer to Hire Remote Developers fro...
logixshapers59
 
PDF
유니티에서 Burst Compiler+ThreadedJobs+SIMD 적용사례
Seongdae Kim
 
PPTX
Tally_Basic_Operations_Presentation.pptx
AditiBansal54083
 
PDF
MiniTool Partition Wizard 12.8 Crack License Key LATEST
hashhshs786
 
PPTX
Tally software_Introduction_Presentation
AditiBansal54083
 
PDF
[Solution] Why Choose the VeryPDF DRM Protector Custom-Built Solution for You...
Lingwen1998
 
PPTX
Agentic Automation: Build & Deploy Your First UiPath Agent
klpathrudu
 
PPTX
Homogeneity of Variance Test Options IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
PDF
Download Canva Pro 2025 PC Crack Full Latest Version
bashirkhan333g
 
PPTX
Home Care Tools: Benefits, features and more
Third Rock Techkno
 
PPTX
In From the Cold: Open Source as Part of Mainstream Software Asset Management
Shane Coughlan
 
PPTX
Change Common Properties in IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
PDF
Driver Easy Pro 6.1.1 Crack Licensce key 2025 FREE
utfefguu
 
PDF
Linux Certificate of Completion - LabEx Certificate
VICTOR MAESTRE RAMIREZ
 
PDF
Automate Cybersecurity Tasks with Python
VICTOR MAESTRE RAMIREZ
 
PPTX
ChiSquare Procedure in IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
4K Video Downloader Plus Pro Crack for MacOS New Download 2025
bashirkhan333g
 
HiHelloHR – Simplify HR Operations for Modern Workplaces
HiHelloHR
 
Digger Solo: Semantic search and maps for your local files
seanpedersen96
 
iTop VPN With Crack Lifetime Activation Key-CODE
utfefguu
 
Empower Your Tech Vision- Why Businesses Prefer to Hire Remote Developers fro...
logixshapers59
 
유니티에서 Burst Compiler+ThreadedJobs+SIMD 적용사례
Seongdae Kim
 
Tally_Basic_Operations_Presentation.pptx
AditiBansal54083
 
MiniTool Partition Wizard 12.8 Crack License Key LATEST
hashhshs786
 
Tally software_Introduction_Presentation
AditiBansal54083
 
[Solution] Why Choose the VeryPDF DRM Protector Custom-Built Solution for You...
Lingwen1998
 
Agentic Automation: Build & Deploy Your First UiPath Agent
klpathrudu
 
Homogeneity of Variance Test Options IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
Download Canva Pro 2025 PC Crack Full Latest Version
bashirkhan333g
 
Home Care Tools: Benefits, features and more
Third Rock Techkno
 
In From the Cold: Open Source as Part of Mainstream Software Asset Management
Shane Coughlan
 
Change Common Properties in IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
Driver Easy Pro 6.1.1 Crack Licensce key 2025 FREE
utfefguu
 
Linux Certificate of Completion - LabEx Certificate
VICTOR MAESTRE RAMIREZ
 
Automate Cybersecurity Tasks with Python
VICTOR MAESTRE RAMIREZ
 
ChiSquare Procedure in IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 

JSON in MySQL and MariaDB Databases

  • 1. { JSON } in MySQL and MariaDB Databases Federico Razzoli
  • 2. € whoami ● Federico Razzoli ● Freelance consultant ● Working with databases since 2000 [email protected] federico-razzoli.com ● I worked as a consultant for Percona and Ibuildings (mainly MySQL and MariaDB) ● I worked as a DBA for fast-growing companies like Catawiki, HumanState, TransferWise
  • 4. JSON Support ● MySQL 7.0 has a JSON type and JSON functions ● MariaDB 10.2 has JSON alias (LONGTEXT) and JSON functions ○ From MariaDB 10.4 JSON columns must contain valid JSON data
  • 5. JSON Type Benefits ● Persons from both MySQL and MariaDB state that their approach is faster ○ Surprise, surprise! ● MySQL format is smaller ● When updating a property, MySQL does not rewrite the whole JSON document ● MySQL binary log only contains the modified properties ○ binlog_row_value_options = 'PARTIAL_JSON' ● However, in MySQL 8, make sure that: ○ Default_tmp_storage_engine = 'TEMPTABLE'
  • 6. JSON Features Comparison ● Let’s compare JSON features, and more generic features that are useful working with JSON ● MySQL 8.0 / MariaDB 10.5 ● MySQL only: ○ Index arrays (requires multi-valued indexes) ○ Schema validation ○ JSON_TABLE() ○ Functional index / Index on VIRTUAL column ● MariaDB only: ○ CONNECT (use a JSON file as a table) ○ Stored aggregate functions
  • 8. JSON in relational databases? ● Relational databases are schemaful ● All rows must have the same columns (name, type) ○ (though NULL is often use to relax the schema) ● CHECK constraints: ○ email VARCHAR(100) CHECK (email LIKE '_%@_%._%') ○ birth_date DATE, death_date DATE, CHECK (birth_date <= death_date) ● UNIQUE constraint ● Referential constraints (foreign keys): ○ Each row in a child table matches a row in a parent table
  • 9. JSON in relational databases? ● JSON is usually schemaless ● Two different objects can have different structures: { "product-type": "shirt", "cost": 10.0, "size": "M" } { "product-type": "phone", "cost": 69.99, "size": [6.37, 2.9, 0.3], "os": "Android" }
  • 10. JSON in relational databases? ● How would you store heterogeneous products in a relational database?
  • 11. JSON in relational databases? ● How would you store heterogeneous products in a relational database? ● One table per product type? ○ Cannot enforce UNIQUE constraint ○ Try to find a product that could be of any type… ○ Try to get the min and max costs...
  • 12. JSON in relational databases? ● How would you store heterogeneous products in a relational database? ● One table with one column for each property, NULL where it is not used? ○ Adding a product implies a slow, painful ALTER TABLE ○ If products type is deleted, obsolete columns tend to remain forever ○ Big table is bad for operations (backup, repair…) ○ INSERTs are slow ○ SELECT *
  • 13. JSON in relational databases? ● How would you store heterogeneous products in a relational database? ● One main table with common properties, and one separate table for each product type? ○ You can now see min/max costs, or find a product of any type ○ Many JOINs
  • 14. JSON in relational databases? ● How would you store heterogeneous products in a relational database? ● Entity-Attribute-Value pattern (EAV)? ○ Store all data as texts ○ Crazy amount of JOINs
  • 15. JSON in relational databases? ● How would you store heterogeneous products in a relational database? ● Single table, where all non-common property are stored as JSON ○ Still not perfect ○ But it’s good enough
  • 16. JSON in relational databases? CREATE TABLE product ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, type VARCHAR(50) NOT NULL, name VARCHAR(50) NOT NULL, cost DECIMAL(10, 2) NOT NULL, quantity INT UNSIGNED NOT NULL, attributes JSON NOT NULL );
  • 18. Materialising Properties CREATE TABLE product ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, type VARCHAR(50), name VARCHAR(50) NOT NULL, cost DECIMAL(10, 2) NOT NULL, quantity INT UNSIGNED NOT NULL, attributes JSON NOT NULL, colour VARCHAR(50) AS (JSON_UNQUOTE( JSON_EXTRACT(attributes, '$.colour') )) STORED );
  • 19. MySQL shortcut CREATE TABLE product ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, type VARCHAR(50), name VARCHAR(50) NOT NULL, cost DECIMAL(10, 2) NOT NULL, quantity INT UNSIGNED NOT NULL, attributes JSON NOT NULL, colour VARCHAR(50) AS (attributes->>'$.colour') VIRTUAL );
  • 20. Index on a Property CREATE TABLE product ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, type VARCHAR(50), name VARCHAR(50) NOT NULL, cost DECIMAL(10, 2) NOT NULL, quantity INT UNSIGNED NOT NULL, attributes JSON NOT NULL, colour VARCHAR(50) AS (attributes->>'$.colour') VIRTUAL, INDEX idx_colour (type, colour) );
  • 21. Index on a Property SELECT id FROM product WHERE type = 'FURNITURE' AND colour = 'grey' ; -- only uses the index in MySQL SELECT id FROM product WHERE type = 'FURNITURE' AND attributes->>'$.colour' = 'grey' ;
  • 22. Indexing Properties CREATE TABLE product ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, type VARCHAR(50), name VARCHAR(50) NOT NULL, cost DECIMAL(10, 2) NOT NULL, quantity INT UNSIGNED NOT NULL, attributes JSON NOT NULL, furniture_colour VARCHAR(50) AS (IF(type = 'FURNITURE', attributes->>'$.colour', NULL )) VIRTUAL, INDEX idx_colour (furniture_colour)
  • 24. Indexing ARRAYS ● MySQL and MariaDB historically don’t support arrays ● Now they can use JSON arrays as “regular” arrays ● MySQL 8.0 supports Multi-Valued Indexes, that allow to index these arrays ○ Can be used to index JSON objects, not covered here
  • 25. Indexing Arrays CREATE TABLE `order` ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, customer_id INT UNSIGNED NOT NULL, product_ids JSON NOT NULL, INDEX idx_products ( (CAST(product_ids AS UNSIGNED ARRAY)) ) ); INSERT INTO `order` (customer_id, product_ids) VALUES (24, JSON_ARRAY(10, 20, 30));
  • 26. Indexing Arrays SELECT DISTINCT customer_id FROM `order` WHERE 20 MEMBER OF (product_ids); ● JSON_CONTAINS() ● JSON_OVERLAPS()
  • 28. Foreign Keys on Properties CREATE TABLE product ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, type VARCHAR(50), ... furniture_colour INT UNSIGNED AS (IF(type = 'FURNITURE', attributes->>'$.colour', NULL )) STORED, INDEX idx_furniture_colour (furniture_colour), FOREIGN KEY fk_furniture_colour (furniture_colour) REFERENCES furniture_colour (id) );
  • 29. Not suggesting to use Foreign Keys ● They come with several penalties ○ Slower writes ○ Propagated locks (for CASCADE FKs) ○ Limitations (only InnoDB, no partitions) ○ Cannot run safe online migrations ● Google for: Federico Razzoli "Foreign Key bugs in MySQL and MariaDB"
  • 30. But... ● But you can do the same without foreign keys ● You can easily add extra columns to furniture_colour ● You don’t have to mind about colour name details (case, extra spaces…) ● You can easily change a colour name ● You keep the JSON documents smaller Basically, you can use the relational databases philosophy While keeping some semi-structured data inside them
  • 32. Validating Against a JSON Schema ● Both MySQL and MariaDB only accept valid JSON documents in JSON columns ● The CHECK clause defines the rules that determine if a row is valid ● JSON_SCHEMA_VALID() in MySQL validates a JSON document against a JSON Schema ○ json-schema.org ○ Draft 4 ○ But from my tests we can use drafts 6 or 7
  • 33. Validating Schema SELECT JSON_SCHEMA_VALID(@schema, @document); SELECT JSON_SCHEMA_VALID(( SELECT schema FROM schemas WHERE type = 'furniture' ), document) FROM product WHERE id = 24 ;
  • 34. Validating Schema Suppose we want to validate objects of this type: { "material": "iron", "colour": "grey", "size": [1.5, 1.5, 1.0] }
  • 35. { "$id": "https://federico-razzoli.com/schemas/furniture", "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "material": { "type": "string", "enum": ["iron", "wood"] }, "size": { "type": "array", "items": { "type": "number", "minItems": 3, "maxItems": 3 } }, "colour": { "type": "string" } }, "required": ["material", "size"] }
  • 36. Debugging a JSON Schema ● SELECT JSON_SCHEMA_VALID() + SHOW WARNINGS ● JSON_SCHEMA_VALIDATION_REPORT()
  • 38. Default Properties ● We can have a JSON document with the default properties ● And only store non-default values in each regular JSON document ● This is useful: ○ For large JSON objects (eg. software configuration) ○ For objects whose defaults may change (eg. software whose settings can be set per user and per team)
  • 39. Merging Documents -- get user settings SET @user_conf := ( SELECT json_settings FROM user_configuration WHERE id = 24 ); -- get team settings SET @team_conf := ( SELECT json_settings FROM team_configuration WHERE id = 123 ); -- merge them. user settings overwrite team settings SELECT JSON_MERGE_PATCH(@team_conf, @user_conf);
  • 40. JSON_MERGE_PATCH() example mysql> SELECT JSON_MERGE_PATCH( '{"items-per-page": 24, "suppress_warnings": true}', '{"suppress_warnings": false}') AS configuration; +----------------------------------------------------+ | configuration | +----------------------------------------------------+ | {"items-per-page": 24, "suppress_warnings": false} | +----------------------------------------------------+
  • 42. JSON_ARRAYAGG(), JSON_OBJECTAGG() ● Available in: ○ MySQL 5.7 ○ MariaDB 10.5, currently not GA ● However, they are: ○ Simple to emulate with GROUP_CONCAT() ○ Easy to code with MariaDB Stored Aggregate Functions (10.3)
  • 43. JSON_ARRAYAGG() mysql> SELECT type, JSON_ARRAYAGG(colour) AS colours -> FROM product -> GROUP BY type -> ORDER BY type; +-------+-----------------------------------+ | type | colours | +-------+-----------------------------------+ | chair | ["green", "blue", "red", "black"] | | shelf | ["white", "brown"] | | table | ["white", "gray", "black"] | +-------+-----------------------------------+
  • 44. JSON_OBJECTAGG(): one document mysql> SELECT -> JSON_PRETTY( -> JSON_OBJECTAGG(variable, value) -> ) AS settings -> FROM config G *************************** 1. row *************************** settings: { "datadir": "/var/mysql/data", "log_bin": "1", "general_log": "0", "slow_query_log": "0", "innodb_log_file_size": "1G", "innodb_log_buffer_size": "16M", "innodb_buffer_pool_size": "16G" }
  • 45. JSON_OBJECTAGG() nested objects mysql> SELECT -> JSON_PRETTY( -> JSON_OBJECTAGG( -> variable, -> JSON_OBJECT( -> 'type', type, -> 'value', value -> ) -> ) -> ) AS settings -> FROM config;
  • 46. JSON_OBJECTAGG() nested objects settings: { "datadir": { "type": "string", "value": "/var/mysql/data" }, "log_bin": { "type": "bool", "value": "1" }, ... }
  • 47. JSON_OBJECTAGG(): one document per row mysql> SELECT JSON_OBJECTAGG(variable, value) AS settings -> FROM config -> GROUP BY variable; +------------------------------------+ | settings | +------------------------------------+ | {"datadir": "/var/mysql/data"} | | {"general_log": "0"} | | {"innodb_buffer_pool_size": "16G"} | | {"innodb_log_buffer_size": "16M"} | | {"innodb_log_file_size": "1G"} | | {"log_bin": "1"} | | {"slow_query_log": "0"} | +------------------------------------+
  • 49. JSON_TABLE() ● Only MySQL 8 ● Transforms a JSON document into a table ● Each property, or some properties, become a table column ● Properties are identified by JSON Path expressions
  • 50. JSON_TABLE() example { "customers": [ { "name": "John Doe", "emails": ["[email protected]"], "phone": "123456" }, { "name": "Jane Dee", "emails": ["[email protected]"], "phone": "987654" }, { "name": "Donald Duck", "emails": [] } ], "products": [], "orders": [] }
  • 51. JSON_TABLE() example SELECT * FROM JSON_TABLE( @customers, '$.customers[*]' COLUMNS ( id FOR ORDINALITY, name VARCHAR(50) PATH '$.name', primary_email VARCHAR(50) PATH '$.emails[0]', phone VARCHAR(50) PATH '$.phone' DEFAULT '"UNKNOWN"' ON EMPTY NULL ON ERROR ) ) AS customers;
  • 52. JSON_TABLE() example +------+-------------+---------------+---------+ | id | name | primary_email | phone | +------+-------------+---------------+---------+ | 1 | John Doe | [email protected] | 123456 | | 2 | Jane Dee | [email protected] | 987654 | | 3 | Donald Duck | NULL | UNKNOWN | +------+-------------+---------------+---------+
  • 54. What CONNECT is ● Connect is a storage engine for MariaDB ○ Won’t compile on MySQL or Percona Server ● Reads data from different data sources: ○ Remote tables (MySQL protocol, ODBC, JDBC) ○ Files in various formats (JSON, XML, CSV, custom formats…) ○ Special data sources ○ Transformed data from other tables (pivot, …)
  • 55. CONNECT and JSON ● JSON Table Type (10.1) ● On Windows, can read data from REST APIs (not easy to do) ● CONNECT comes with a library of JSON UDFs ○ Probably not battle-tested as the current built-in functions
  • 56. Thank you for listening! Federico [email protected]