SlideShare a Scribd company logo
MySQL Document store:
SQL and NoSQL united
Giuseppe Maxia
Vmware, Inc
1
The battle is over.
SQL and noSQL can live together.
Who's this guy?
About me
‣ Giuseppe Maxia, a.k.a. "The Data Charmer"
‣ QA Architect at VMware
‣ 25+ years development and DB experience
‣ Long timer MySQL community member.
‣ Oracle ACE Director
‣ Blog: http://datacharmer.blogspot.com
‣ Twitter: @datacharmer
2
A
‣ Document store in a nutshell
‣ X-Protocol overview
‣ X-Plugin installation
‣ MySQL shell installation
‣ Getting started
‣ Example: with the shell
‣ Example: data to and from MongoDB
‣ A look inside
Agenda
3
Better be clear about this
Disclaimer
‣ This is community work.
‣ Non affiliation:
• I don't work for Oracle. All I say here, good or bad, is my
opinion.
‣ Not talking for my company:
• All I say is my own stuff. My company does not influence
or censor what I say here.
4
This technology does not work with every version
Requirements
‣ MySQL 5.7.12 or later (contains the X-Plugin)
‣ MySQL shell (separate product)
5
This is not intuitive
How DBAs see data
6
person_id
name
dept_id
Person
dept_id
name
Dept
empl_ID
name
Title
person_id
dept_id
person_dept
person_id
title_id
start_date
end_date
person_title
person_id
salary
start_date
end_date
salary
This is driven by most programming languages
How developers see data
7
it's a clash of data structures
DBAs vs. developers
8
xxxx: {
xxxxxxxx
aaaaaa,
yyyyy: {
yyyyyyyyy,
yyyyyyyyy,
yyyyyyyyy
},
z: [
{ zzzzz, zzzzz, zzzz},
{ zzzzz, zzzzz, zzzz},
{ zzzzz, zzzzz, zzzz}
[
}
xxxx
xxxx
xxxx
xxxx
aaaa
aaaa
aaaa
yyyy
yyyy
yyyy
aaaa
xxxx
xxxx_aaaa
xxxx
yyyy
yyyy
xxxx_yyyy
xxx
zzz
zzz
zzzz
A new protocol to talk to MySQL
‣ extends and replaces the traditional client/
server protocol
‣ allows asynchronous communication to the
server
‣ uses different API calls
• Javascript
• Python
• C#
• Java
X- Protocol overview
9
It should be easy to switch
Universal API
MySQL Shell JavaScript Code
// Create a new collection
var myColl = db.createCollection('my_collection');
// Insert a document
myColl.add( { name: 'Sakila', age: 15 } ).execute();
// Insert several documents at once
myColl.add( [
{ name: 'Susanne', age: 24 },
{ name: 'Mike', age: 39 } ] ).execute();
10
It looks really easy to switch!
Universal API
MySQL Shell Python Code
# Create a new collection
myColl = db.createCollection('my_collection')
# Insert a document
myColl.add( { 'name': 'Sakila', 'age':15 } ).execute()
# Insert several documents at once
myColl.add( [
{ 'name': 'Susanne', 'age': 24 },
{ 'name': 'Mike', 'age' : 39 } ] ).execute()
11
The document store is not in the
server by default
‣ MySQL server does not include the X-protocol
‣ You need to install a plugin for this
‣ and you need the MySQL shell (separate
product) to use it
12
The server is GA , but ...
!! WARNING !!
‣ The document store comes with MySQL 5.7.12+
‣ HOWEVER
• The tools ARE NOT GA quality
• They are, actually, pretty much alpha software
‣ Be careful when using it in production
13
From the manual
"Using MySQL as a document store is currently a
preproduction feature"
https://dev.mysql.com/doc/refman/5.7/en/
document-store.html 14
There are several components to the document store
Readiness (as of June 2017)
15
MySQL
SERVER
5.7.12+
PLUGIN
SHELL
1.0.9
CONNECTORS
GA GA GA Alpha
node.js
java
javascript
python
.net
c++
The plugin comes with the server, but you need to enable it
X-Plugin installation
‣ Three methods:
• with mysqlsh
• at startup, using --plugin-load=mysqlx=mysqlx.so
• in SQL, using INSTALL PLUGIN
16
Using the mysql shell itself
Method 1 : with mysqlsh
mysqlsh 
--classic 
--user=msandbox 
--password=msandbox 
--port=3306 
--host=127.0.0.1 
--dba enableXProtocol
17
When we start the server
Method 2 : at startup
mysqld [...] --plugin-load=mysqlx=mysqlx.so 
--mysqlx-port=15000
# or in the configuration file
[mysqld]
# ...
plugin-load=mysqlx=mysqlx.so
mysqlx-port=15000
18
At any moment
Method 3 : in SQL
install plugin mysqlx soname 'mysqlx.so';
19
Gotchas
‣ X-Plugin listens to port 33060
‣ When you install with method 1, you use port
3306
‣ Afterwards, you use port 33060
20
You need the new client to use the new features
MySQL Shell installation
21
There are packages for most operating systems
MySQL Shell installation
22
Instead of installing ...
Shell with Docker
‣ Using a Docker image
‣ Shell ready to use
‣ No side effects
23
MySQL shell image
not updated
since ~1 year ago
Using the latest mysqlsh release, there is a workaround
However ...
docker run -d 
-v $PWD/mysql-shell/bin/mysqlsh:/usr/bin/mysqlsh 
-v ~/data:/data 
--name mybox 
-e MYSQL_ROOT_PASSWORD=secret 
mysql/mysql-server
docker run -ti mybox bash
24
Let's practice with real data
‣ Install MySQL 5.7.18
‣ load plugin
‣ Download the world_x database
• https://dev.mysql.com/doc/index-other.html
‣ load the database
‣ connect using mysql shell
Getting started
25
Getting ready
Examples with the shell
26
Some things have two faces
As seen from the old client
~/sandboxes/msb_5_7_17/use world_x
mysql [localhost] {msandbox} (world_x) > show tables;
+-------------------+
| Tables_in_world_x |
+-------------------+
| City |
| Country |
| CountryInfo |
| CountryLanguage |
+-------------------+
4 rows in set (0.00 sec)
27
Welcome to the machine!
And from the new client (1)
$ mysqlsh 
--uri msandbox:msandbox@127.0.0.1:33060/world_x
Creating a Session to 'msandbox@127.0.0.1:33060/
world_x'
Node Session successfully established. Default schema
`mysql_x` accessible through db.
Welcome to MySQL Shell 1.0.9
[...]
Type 'help', 'h' or '?' for help, type 'quit' or
'q' to exit.
Currently in JavaScript mode. Use sql to switch to
SQL mode and execute queries.
mysql-js>
28
Welcome to the machine!
And from the new client (2)
mysql-js> db.getTables()
{
"City": <Table:City>,
"Country": <Table:Country>,
"CountryLanguage": <Table:CountryLanguage>
}
mysql-js> db.getCollections()
{
"CountryInfo": <Collection:CountryInfo>
}
mysql-js>
29
Schema-less!
Starting something new
mysql-js> nc=db.createCollection('person')
<Collection:person>
mysql-js>
mysql-js> db.getCollections()
{
"CountryInfo": <Collection:CountryInfo>,
"person": <Collection:person>
}
mysql-js>
30
REALLY schema-less!
Inserting data
mysql-js> nc.add({ name: "Joe", city: "Paris"})
Query OK, 1 item affected (0.00 sec)
mysql-js> nc.add({ name: "Frank", where_are_you_from:
"London"})
Query OK, 1 item affected (0.01 sec)
31
This reminds me of something ...
Retrieving data
mysql-js> nc.find()
[
{
"_id": "6eee6f07ab66e611564dfeeead98f1ef",
"name": "Frank",
"where_are_you_from": "London"
},
{
"_id": "94b470f7aa66e611564dfeeead98f1ef",
"city": "Paris",
"name": "Joe"
}
]
2 documents in set (0.00 sec)
32
The general log shows what we were doing
Back to the old side
33
CREATE TABLE `world_x`.`person` (doc JSON,_id
VARCHAR(32) GENERATED ALWAYS AS
(JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) STORED
PRIMARY KEY) CHARSET utf8mb4 ENGINE=InnoDB
Query INSERT INTO `world_x`.`person` (doc) VALUES
('{"_id":"94b470f7aa66e611564dfeeead98f1ef","city
":"Paris","name":"Joe"}')
Query INSERT INTO `world_x`.`person` (doc) VALUES
('{"_id":"6eee6f07ab66e611564dfeeead98f1ef","name
":"Frank","where_are_you_from":"London"}')
A classical organization with sales
A complex example
34
person
sales
categories
departments
locations countries
customersclass
The classical organization as a SQL result
SQL to JSON (1)
select name, sale_date, sale_amount as '$$$', customer,
class_name
from person
inner join sales using (person_id)
inner join customers using (customer_id)
inner join class c on (c.class_id = sales.class_id);
+--------+------------+-------+-------------+------------+
| name | sale_date | $$$ | customer | class_name |
+--------+------------+-------+-------------+------------+
| Frank | 2003-10-01 | 23000 | DataSmart | software |
| Frank | 2003-10-12 | 45000 | NewHardware | hardware |
| Frank | 2003-11-04 | 60000 | DataSmart | services |
| Susan | 2003-11-02 | 25000 | ViewData | software |
| Susan | 2003-10-13 | 18000 | SmartEdu | services |
| Martin | 2003-10-12 | 50000 | SmartEdu | hardware |
+--------+------------+-------+-------------+------------+
35
The classical organization as a collection of documents
SQL to JSON (2)
36
The world_x database comes with some beefy data
A bigger collection
mysql-js> db.getCollections()
{
"CountryInfo": <Collection:CountryInfo>,
"person": <Collection:person>
}
mysql-js> ci=db.getCollection('CountryInfo')
<Collection:CountryInfo>
37
The data is in layers
Sample data from world_x
mysql-js> ci.find().limit(1)
[
{
"GNP": 828,
"IndepYear": null,
"Name": "Aruba",
"_id": "ABW",
"demographics": {
"LifeExpectancy": 78.4000015258789,
"Population": 103000
},
"geography": {
"Continent": "North America",
"Region": "Caribbean",
"SurfaceArea": 193
},
"government": {
"GovernmentForm": "Nonmetropolitan Territory of The Netherlands",
"HeadOfState": "Beatrix"
}
}
]
38
Not always easy to get
Complex queries are possible
39
Since they are both schema-less ...
‣ From MySQL to MongoDB
• extract data from a document store
• feed it to MongoDB
‣ From MongoDB to MySQL
• create collection
• extract data
• filter off the oddities
• feed it to MySQL shell
Examples: to and from MongoDB
40
Extracting data
From MySQL to Mongoldb (1)
// extract.py
import mysqlx
import json
session = mysqlx.get_session( ... )
schema = session.get_schema('world_x')
collection = schema.get_collection('CountryInfo')
result = collection.find().execute()
docs = result.fetch_all()
for doc in docs:
doc = dict(doc)
print(json.dumps(doc, indent=4))
session.close()
# python extract.py > /data/country_info.json
41
import data to mongoldb
From MySQL to Mongoldb (2)
mongoimport --db test --collection countries 
--drop --file /data/country_info.json
42
First create the collection
From MongoDB to MySQL (1)
mysql-js> db.createCollection('restaurants')
43
Export the data from MongoDB
From MongoDB to MySQL (2)
docker exec -ti mongo mongo --quiet 
--eval 'DBQuery.shellBatchSize=300; var
all=db.restaurants.find() ; all' 
| perl -pe 's/(?:ObjectId|ISODate)(("[^"]+"))/
$1/g' 
> all_recs.json
44
There is data like this:
Why do we need to filter
{
"_id" : ObjectId("57b81d385957bb0d60511ce5"),
"borough" : "Bronx",
"cuisine" : "Bakery",
"grades" : [
{
"date" : ISODate("2014-03-03T00:00:00Z"),
"grade" : "A",
"score" : 2
},
],
"name" : "Morris Park Bake Shop",
"restaurant_id" : "30075445"
}
45
Importing into MySQL
schema = session.get_schema('test')
collection = schema.create_collection('restaurants')
with open('all_recs.json', 'r') as json_data:
for line in json_data:
skip=re.match('Type', line)
if not skip:
rec = json.loads(line)
collection.add(rec).execute()
46
What's a MySQL Document?
A look inside
‣ mysqlsh calls it a "collection"
‣ mysql calls it a table
• with a GENERATED _id field
• with a json field
47
The old client view
mysql
show tables;
+-------------------+
| Tables_in_world_x |
+-------------------+
| City |
| Country |
| CountryInfo |
| CountryLanguage |
+-------------------+
4 rows in set (0.00 sec)
48
The document store view
mysqlsh
mysql-js> db.getCollections()
{
"CountryInfo": <Collection:CountryInfo>
}
mysql-js> db.getTables()
{
"City": <Table:City>,
"Country": <Table:Country>,
"CountryLanguage": <Table:CountryLanguage>
}
49
The old client view
mysql
show create table CountryInfoG
******* 1. row ***************************
Table: CountryInfo
Create Table: CREATE TABLE `CountryInfo` (
`doc` json DEFAULT NULL,
`_id` varchar(32) GENERATED ALWAYS AS
(json_unquote(json_extract(`doc`,'$._id'))) STORED
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
50
The "truth"
general log
SELECT C.table_name AS name,
IF(ANY_VALUE(T.table_type)='VIEW', 'VIEW', IF(COUNT(*)
= COUNT(CASE WHEN (column_name = 'doc' AND data_type =
'json') THEN 1 ELSE NULL END) + COUNT(CASE WHEN
(column_name = '_id' AND generation_expression =
'json_unquote(json_extract(`doc`,''$._id''))') THEN 1
ELSE NULL END) + COUNT(CASE WHEN (column_name != '_id'
AND generation_expression RLIKE '^(json_unquote[[.
(.]])?json_extract[[.(.]]`doc`,''[[.$.]]([[...]]
[^[:space:][...]]+)+''[[.).]]{1,2}$') THEN 1 ELSE NULL
END), 'COLLECTION', 'TABLE')) AS type FROM
information_schema.columns AS C LEFT JOIN
information_schema.tables AS T USING (table_name)WHERE
C.table_schema = 'world_x' GROUP BY C.table_name ORDER
BY C.table_name
51
I'd say it needs more integration
how x-plugin finds "collections"
SELECT C.table_name AS name, IF(ANY_VALUE(T.table_type)='VIEW', 'VIEW',
IF(COUNT(*) = COUNT(CASE WHEN (column_name = 'doc' AND data_type = 'json') THEN 1
ELSE NULL END) + COUNT(CASE WHEN (column_name = '_id' AND generation_expression =
'json_unquote(json_extract(`doc`,''$._id''))') THEN 1 ELSE NULL END) + COUNT(CASE
WHEN (column_name != '_id' AND generation_expression RLIKE '^(json_unquote[[.
(.]])?json_extract[[.(.]]`doc`,''[[.$.]]([[...]][^[:space:][...]]+)+''[[.).]]
{1,2}$') THEN 1 ELSE NULL END), 'COLLECTION', 'TABLE')) AS type FROM
information_schema.columns AS C LEFT JOIN information_schema.tables AS T USING
(table_name)WHERE C.table_schema = 'world_x' GROUP BY C.table_name ORDER BY
C.table_name
+-----------------+------------+
| name | type |
+-----------------+------------+
| City | TABLE |
| Country | TABLE |
| CountryInfo | COLLECTION |
| CountryLanguage | TABLE |
+-----------------+------------+
52
A few tricks that could be useful
More with mysql shell
‣ Using mysqlsh to export in JSON format from
regular MySQL tables
‣ Running mysqlsh in Docker without a dedicated
container.
53
where to find the examples used in this presentation
Examples
https://github.com/datacharmer/mysql-document-store
54
Q & A
55

More Related Content

What's hot (20)

PPTX
Query logging with proxysql
YoungHeon (Roy) Kim
 
PPTX
MySQL Utilities -- Cool Tools For You: PHP World Nov 16 2016
Dave Stokes
 
PDF
How to Avoid Pitfalls in Schema Upgrade with Galera
Sveta Smirnova
 
PDF
MariaDB and Clickhouse Percona Live 2019 talk
Alexander Rubin
 
PPTX
DataStax: An Introduction to DataStax Enterprise Search
DataStax Academy
 
PPTX
My sql failover test using orchestrator
YoungHeon (Roy) Kim
 
PDF
Advanced VCL: how to use restart
Fastly
 
PDF
MySQL Performance Schema in Action
Sveta Smirnova
 
PDF
New features in Performance Schema 5.7 in action
Sveta Smirnova
 
PDF
Building Distributed System with Celery on Docker Swarm - PyCon JP 2016
Wei Lin
 
PDF
Using Apache Spark and MySQL for Data Analysis
Sveta Smirnova
 
PDF
Make Your Life Easier With Maatkit
MySQLConference
 
PDF
NYC Cassandra Day - Java Intro
Christopher Batey
 
PDF
VCL template abstraction model and automated deployments to Fastly
Fastly
 
PDF
Fluentd 20150918 no_demo_public
Saewoong Lee
 
PDF
Summary tables with flexviews
Justin Swanhart
 
PDF
Installing postgres & postgis
John Ashmead
 
PDF
How to migrate from MySQL to MariaDB without tears
Sveta Smirnova
 
PDF
Knex Postgresql Migration
TechMaster Vietnam
 
PDF
OpenWorld 2014 - Schema Management: versioning and automation with Puppet and...
Frederic Descamps
 
Query logging with proxysql
YoungHeon (Roy) Kim
 
MySQL Utilities -- Cool Tools For You: PHP World Nov 16 2016
Dave Stokes
 
How to Avoid Pitfalls in Schema Upgrade with Galera
Sveta Smirnova
 
MariaDB and Clickhouse Percona Live 2019 talk
Alexander Rubin
 
DataStax: An Introduction to DataStax Enterprise Search
DataStax Academy
 
My sql failover test using orchestrator
YoungHeon (Roy) Kim
 
Advanced VCL: how to use restart
Fastly
 
MySQL Performance Schema in Action
Sveta Smirnova
 
New features in Performance Schema 5.7 in action
Sveta Smirnova
 
Building Distributed System with Celery on Docker Swarm - PyCon JP 2016
Wei Lin
 
Using Apache Spark and MySQL for Data Analysis
Sveta Smirnova
 
Make Your Life Easier With Maatkit
MySQLConference
 
NYC Cassandra Day - Java Intro
Christopher Batey
 
VCL template abstraction model and automated deployments to Fastly
Fastly
 
Fluentd 20150918 no_demo_public
Saewoong Lee
 
Summary tables with flexviews
Justin Swanhart
 
Installing postgres & postgis
John Ashmead
 
How to migrate from MySQL to MariaDB without tears
Sveta Smirnova
 
Knex Postgresql Migration
TechMaster Vietnam
 
OpenWorld 2014 - Schema Management: versioning and automation with Puppet and...
Frederic Descamps
 

Similar to MySQL document_store (20)

PDF
MySQL as a Document Store
Dave Stokes
 
ODP
MySQL Without the MySQL -- Oh My!
Dave Stokes
 
PDF
MySQL Document Store -- SCaLE 17x Presentation
Dave Stokes
 
PPTX
MySQL Without the SQL - Oh My! -> MySQL Document Store -- Confoo.CA 2019
Dave Stokes
 
PPTX
Discover the Power of the NoSQL + SQL with MySQL
Dave Stokes
 
PPTX
Discover The Power of NoSQL + MySQL with MySQL
Dave Stokes
 
PPTX
MySQL Without the SQL -- Oh My! Longhorn PHP Conference
Dave Stokes
 
PDF
Open Source World June '21 -- JSON Within a Relational Database
Dave Stokes
 
PDF
MySQL Without the SQL - Oh My! August 2nd presentation at Mid Atlantic Develo...
Dave Stokes
 
PDF
Json within a relational database
Dave Stokes
 
PDF
MySQL Without the SQL -- Oh My!
Data Con LA
 
PDF
Datacon LA - MySQL without the SQL - Oh my!
Dave Stokes
 
PDF
MySQL Document Store (Oracle Code Warsaw 2018)
Vittorio Cioe
 
PDF
20171104 hk-py con-mysql-documentstore_v1
Ivan Ma
 
PDF
Oracle Code Event - MySQL JSON Document Store
Mark Swarbrick
 
PDF
MySQL Document Store - A Document Store with all the benefts of a Transactona...
Olivier DASINI
 
PDF
MySQL without the SQL -- Cascadia PHP
Dave Stokes
 
PDF
Node.js and the MySQL Document Store
Rui Quelhas
 
PDF
20160821 coscup-my sql57docstorelab01
Ivan Ma
 
PDF
MySQL Document Store
Mario Beck
 
MySQL as a Document Store
Dave Stokes
 
MySQL Without the MySQL -- Oh My!
Dave Stokes
 
MySQL Document Store -- SCaLE 17x Presentation
Dave Stokes
 
MySQL Without the SQL - Oh My! -> MySQL Document Store -- Confoo.CA 2019
Dave Stokes
 
Discover the Power of the NoSQL + SQL with MySQL
Dave Stokes
 
Discover The Power of NoSQL + MySQL with MySQL
Dave Stokes
 
MySQL Without the SQL -- Oh My! Longhorn PHP Conference
Dave Stokes
 
Open Source World June '21 -- JSON Within a Relational Database
Dave Stokes
 
MySQL Without the SQL - Oh My! August 2nd presentation at Mid Atlantic Develo...
Dave Stokes
 
Json within a relational database
Dave Stokes
 
MySQL Without the SQL -- Oh My!
Data Con LA
 
Datacon LA - MySQL without the SQL - Oh my!
Dave Stokes
 
MySQL Document Store (Oracle Code Warsaw 2018)
Vittorio Cioe
 
20171104 hk-py con-mysql-documentstore_v1
Ivan Ma
 
Oracle Code Event - MySQL JSON Document Store
Mark Swarbrick
 
MySQL Document Store - A Document Store with all the benefts of a Transactona...
Olivier DASINI
 
MySQL without the SQL -- Cascadia PHP
Dave Stokes
 
Node.js and the MySQL Document Store
Rui Quelhas
 
20160821 coscup-my sql57docstorelab01
Ivan Ma
 
MySQL Document Store
Mario Beck
 
Ad

More from Giuseppe Maxia (20)

PDF
MySQL NDB 8.0 clusters in your laptop with dbdeployer
Giuseppe Maxia
 
PDF
Test like a_boss
Giuseppe Maxia
 
PDF
Dbdeployer, the universal installer
Giuseppe Maxia
 
PDF
Test complex database systems in your laptop with dbdeployer
Giuseppe Maxia
 
PDF
Dbdeployer
Giuseppe Maxia
 
PDF
Dbdeployer
Giuseppe Maxia
 
PDF
Synchronise your data between MySQL and MongoDB
Giuseppe Maxia
 
PDF
Juggle your data with Tungsten Replicator
Giuseppe Maxia
 
PDF
Tungsten Replicator tutorial
Giuseppe Maxia
 
PDF
Preventing multi master conflicts with tungsten
Giuseppe Maxia
 
PDF
MySQL high availability power and usability
Giuseppe Maxia
 
PDF
Solving MySQL replication problems with Tungsten
Giuseppe Maxia
 
PDF
State of the art of MySQL replication and clustering
Giuseppe Maxia
 
PDF
Testing mysql creatively in a sandbox
Giuseppe Maxia
 
PDF
Mysql 5.5 and 5.6 replication
Giuseppe Maxia
 
PDF
Lightning talks percona live mysql_2012
Giuseppe Maxia
 
PDF
Replication 101
Giuseppe Maxia
 
PDF
Testing early mysql releases in a sandbox
Giuseppe Maxia
 
PDF
Testing mysql creatively in a sandbox
Giuseppe Maxia
 
PDF
Building simple and complex clusters with tungsten replicator
Giuseppe Maxia
 
MySQL NDB 8.0 clusters in your laptop with dbdeployer
Giuseppe Maxia
 
Test like a_boss
Giuseppe Maxia
 
Dbdeployer, the universal installer
Giuseppe Maxia
 
Test complex database systems in your laptop with dbdeployer
Giuseppe Maxia
 
Dbdeployer
Giuseppe Maxia
 
Dbdeployer
Giuseppe Maxia
 
Synchronise your data between MySQL and MongoDB
Giuseppe Maxia
 
Juggle your data with Tungsten Replicator
Giuseppe Maxia
 
Tungsten Replicator tutorial
Giuseppe Maxia
 
Preventing multi master conflicts with tungsten
Giuseppe Maxia
 
MySQL high availability power and usability
Giuseppe Maxia
 
Solving MySQL replication problems with Tungsten
Giuseppe Maxia
 
State of the art of MySQL replication and clustering
Giuseppe Maxia
 
Testing mysql creatively in a sandbox
Giuseppe Maxia
 
Mysql 5.5 and 5.6 replication
Giuseppe Maxia
 
Lightning talks percona live mysql_2012
Giuseppe Maxia
 
Replication 101
Giuseppe Maxia
 
Testing early mysql releases in a sandbox
Giuseppe Maxia
 
Testing mysql creatively in a sandbox
Giuseppe Maxia
 
Building simple and complex clusters with tungsten replicator
Giuseppe Maxia
 
Ad

Recently uploaded (20)

PDF
Alarm in Android-Scheduling Timed Tasks Using AlarmManager in Android.pdf
Nabin Dhakal
 
PPTX
A Complete Guide to Salesforce SMS Integrations Build Scalable Messaging With...
360 SMS APP
 
PDF
Executive Business Intelligence Dashboards
vandeslie24
 
PPT
MergeSortfbsjbjsfk sdfik k
RafishaikIT02044
 
PPTX
Fundamentals_of_Microservices_Architecture.pptx
MuhammadUzair504018
 
PPTX
Human Resources Information System (HRIS)
Amity University, Patna
 
PPTX
Tally software_Introduction_Presentation
AditiBansal54083
 
PDF
Build It, Buy It, or Already Got It? Make Smarter Martech Decisions
bbedford2
 
PDF
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pdf
Varsha Nayak
 
PPTX
3uTools Full Crack Free Version Download [Latest] 2025
muhammadgurbazkhan
 
PDF
GetOnCRM Speeds Up Agentforce 3 Deployment for Enterprise AI Wins.pdf
GetOnCRM Solutions
 
PPTX
The Role of a PHP Development Company in Modern Web Development
SEO Company for School in Delhi NCR
 
PPTX
Feb 2021 Cohesity first pitch presentation.pptx
enginsayin1
 
PPTX
Engineering the Java Web Application (MVC)
abhishekoza1981
 
PPTX
Writing Better Code - Helping Developers make Decisions.pptx
Lorraine Steyn
 
PDF
Digger Solo: Semantic search and maps for your local files
seanpedersen96
 
PDF
Thread In Android-Mastering Concurrency for Responsive Apps.pdf
Nabin Dhakal
 
PDF
Efficient, Automated Claims Processing Software for Insurers
Insurance Tech Services
 
PDF
Alexander Marshalov - How to use AI Assistants with your Monitoring system Q2...
VictoriaMetrics
 
PPTX
Revolutionizing Code Modernization with AI
KrzysztofKkol1
 
Alarm in Android-Scheduling Timed Tasks Using AlarmManager in Android.pdf
Nabin Dhakal
 
A Complete Guide to Salesforce SMS Integrations Build Scalable Messaging With...
360 SMS APP
 
Executive Business Intelligence Dashboards
vandeslie24
 
MergeSortfbsjbjsfk sdfik k
RafishaikIT02044
 
Fundamentals_of_Microservices_Architecture.pptx
MuhammadUzair504018
 
Human Resources Information System (HRIS)
Amity University, Patna
 
Tally software_Introduction_Presentation
AditiBansal54083
 
Build It, Buy It, or Already Got It? Make Smarter Martech Decisions
bbedford2
 
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pdf
Varsha Nayak
 
3uTools Full Crack Free Version Download [Latest] 2025
muhammadgurbazkhan
 
GetOnCRM Speeds Up Agentforce 3 Deployment for Enterprise AI Wins.pdf
GetOnCRM Solutions
 
The Role of a PHP Development Company in Modern Web Development
SEO Company for School in Delhi NCR
 
Feb 2021 Cohesity first pitch presentation.pptx
enginsayin1
 
Engineering the Java Web Application (MVC)
abhishekoza1981
 
Writing Better Code - Helping Developers make Decisions.pptx
Lorraine Steyn
 
Digger Solo: Semantic search and maps for your local files
seanpedersen96
 
Thread In Android-Mastering Concurrency for Responsive Apps.pdf
Nabin Dhakal
 
Efficient, Automated Claims Processing Software for Insurers
Insurance Tech Services
 
Alexander Marshalov - How to use AI Assistants with your Monitoring system Q2...
VictoriaMetrics
 
Revolutionizing Code Modernization with AI
KrzysztofKkol1
 

MySQL document_store

  • 1. MySQL Document store: SQL and NoSQL united Giuseppe Maxia Vmware, Inc 1 The battle is over. SQL and noSQL can live together.
  • 2. Who's this guy? About me ‣ Giuseppe Maxia, a.k.a. "The Data Charmer" ‣ QA Architect at VMware ‣ 25+ years development and DB experience ‣ Long timer MySQL community member. ‣ Oracle ACE Director ‣ Blog: http://datacharmer.blogspot.com ‣ Twitter: @datacharmer 2 A
  • 3. ‣ Document store in a nutshell ‣ X-Protocol overview ‣ X-Plugin installation ‣ MySQL shell installation ‣ Getting started ‣ Example: with the shell ‣ Example: data to and from MongoDB ‣ A look inside Agenda 3
  • 4. Better be clear about this Disclaimer ‣ This is community work. ‣ Non affiliation: • I don't work for Oracle. All I say here, good or bad, is my opinion. ‣ Not talking for my company: • All I say is my own stuff. My company does not influence or censor what I say here. 4
  • 5. This technology does not work with every version Requirements ‣ MySQL 5.7.12 or later (contains the X-Plugin) ‣ MySQL shell (separate product) 5
  • 6. This is not intuitive How DBAs see data 6 person_id name dept_id Person dept_id name Dept empl_ID name Title person_id dept_id person_dept person_id title_id start_date end_date person_title person_id salary start_date end_date salary
  • 7. This is driven by most programming languages How developers see data 7
  • 8. it's a clash of data structures DBAs vs. developers 8 xxxx: { xxxxxxxx aaaaaa, yyyyy: { yyyyyyyyy, yyyyyyyyy, yyyyyyyyy }, z: [ { zzzzz, zzzzz, zzzz}, { zzzzz, zzzzz, zzzz}, { zzzzz, zzzzz, zzzz} [ } xxxx xxxx xxxx xxxx aaaa aaaa aaaa yyyy yyyy yyyy aaaa xxxx xxxx_aaaa xxxx yyyy yyyy xxxx_yyyy xxx zzz zzz zzzz
  • 9. A new protocol to talk to MySQL ‣ extends and replaces the traditional client/ server protocol ‣ allows asynchronous communication to the server ‣ uses different API calls • Javascript • Python • C# • Java X- Protocol overview 9
  • 10. It should be easy to switch Universal API MySQL Shell JavaScript Code // Create a new collection var myColl = db.createCollection('my_collection'); // Insert a document myColl.add( { name: 'Sakila', age: 15 } ).execute(); // Insert several documents at once myColl.add( [ { name: 'Susanne', age: 24 }, { name: 'Mike', age: 39 } ] ).execute(); 10
  • 11. It looks really easy to switch! Universal API MySQL Shell Python Code # Create a new collection myColl = db.createCollection('my_collection') # Insert a document myColl.add( { 'name': 'Sakila', 'age':15 } ).execute() # Insert several documents at once myColl.add( [ { 'name': 'Susanne', 'age': 24 }, { 'name': 'Mike', 'age' : 39 } ] ).execute() 11
  • 12. The document store is not in the server by default ‣ MySQL server does not include the X-protocol ‣ You need to install a plugin for this ‣ and you need the MySQL shell (separate product) to use it 12
  • 13. The server is GA , but ... !! WARNING !! ‣ The document store comes with MySQL 5.7.12+ ‣ HOWEVER • The tools ARE NOT GA quality • They are, actually, pretty much alpha software ‣ Be careful when using it in production 13
  • 14. From the manual "Using MySQL as a document store is currently a preproduction feature" https://dev.mysql.com/doc/refman/5.7/en/ document-store.html 14
  • 15. There are several components to the document store Readiness (as of June 2017) 15 MySQL SERVER 5.7.12+ PLUGIN SHELL 1.0.9 CONNECTORS GA GA GA Alpha node.js java javascript python .net c++
  • 16. The plugin comes with the server, but you need to enable it X-Plugin installation ‣ Three methods: • with mysqlsh • at startup, using --plugin-load=mysqlx=mysqlx.so • in SQL, using INSTALL PLUGIN 16
  • 17. Using the mysql shell itself Method 1 : with mysqlsh mysqlsh --classic --user=msandbox --password=msandbox --port=3306 --host=127.0.0.1 --dba enableXProtocol 17
  • 18. When we start the server Method 2 : at startup mysqld [...] --plugin-load=mysqlx=mysqlx.so --mysqlx-port=15000 # or in the configuration file [mysqld] # ... plugin-load=mysqlx=mysqlx.so mysqlx-port=15000 18
  • 19. At any moment Method 3 : in SQL install plugin mysqlx soname 'mysqlx.so'; 19
  • 20. Gotchas ‣ X-Plugin listens to port 33060 ‣ When you install with method 1, you use port 3306 ‣ Afterwards, you use port 33060 20
  • 21. You need the new client to use the new features MySQL Shell installation 21
  • 22. There are packages for most operating systems MySQL Shell installation 22
  • 23. Instead of installing ... Shell with Docker ‣ Using a Docker image ‣ Shell ready to use ‣ No side effects 23 MySQL shell image not updated since ~1 year ago
  • 24. Using the latest mysqlsh release, there is a workaround However ... docker run -d -v $PWD/mysql-shell/bin/mysqlsh:/usr/bin/mysqlsh -v ~/data:/data --name mybox -e MYSQL_ROOT_PASSWORD=secret mysql/mysql-server docker run -ti mybox bash 24
  • 25. Let's practice with real data ‣ Install MySQL 5.7.18 ‣ load plugin ‣ Download the world_x database • https://dev.mysql.com/doc/index-other.html ‣ load the database ‣ connect using mysql shell Getting started 25
  • 27. Some things have two faces As seen from the old client ~/sandboxes/msb_5_7_17/use world_x mysql [localhost] {msandbox} (world_x) > show tables; +-------------------+ | Tables_in_world_x | +-------------------+ | City | | Country | | CountryInfo | | CountryLanguage | +-------------------+ 4 rows in set (0.00 sec) 27
  • 28. Welcome to the machine! And from the new client (1) $ mysqlsh --uri msandbox:[email protected]:33060/world_x Creating a Session to '[email protected]:33060/ world_x' Node Session successfully established. Default schema `mysql_x` accessible through db. Welcome to MySQL Shell 1.0.9 [...] Type 'help', 'h' or '?' for help, type 'quit' or 'q' to exit. Currently in JavaScript mode. Use sql to switch to SQL mode and execute queries. mysql-js> 28
  • 29. Welcome to the machine! And from the new client (2) mysql-js> db.getTables() { "City": <Table:City>, "Country": <Table:Country>, "CountryLanguage": <Table:CountryLanguage> } mysql-js> db.getCollections() { "CountryInfo": <Collection:CountryInfo> } mysql-js> 29
  • 30. Schema-less! Starting something new mysql-js> nc=db.createCollection('person') <Collection:person> mysql-js> mysql-js> db.getCollections() { "CountryInfo": <Collection:CountryInfo>, "person": <Collection:person> } mysql-js> 30
  • 31. REALLY schema-less! Inserting data mysql-js> nc.add({ name: "Joe", city: "Paris"}) Query OK, 1 item affected (0.00 sec) mysql-js> nc.add({ name: "Frank", where_are_you_from: "London"}) Query OK, 1 item affected (0.01 sec) 31
  • 32. This reminds me of something ... Retrieving data mysql-js> nc.find() [ { "_id": "6eee6f07ab66e611564dfeeead98f1ef", "name": "Frank", "where_are_you_from": "London" }, { "_id": "94b470f7aa66e611564dfeeead98f1ef", "city": "Paris", "name": "Joe" } ] 2 documents in set (0.00 sec) 32
  • 33. The general log shows what we were doing Back to the old side 33 CREATE TABLE `world_x`.`person` (doc JSON,_id VARCHAR(32) GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) STORED PRIMARY KEY) CHARSET utf8mb4 ENGINE=InnoDB Query INSERT INTO `world_x`.`person` (doc) VALUES ('{"_id":"94b470f7aa66e611564dfeeead98f1ef","city ":"Paris","name":"Joe"}') Query INSERT INTO `world_x`.`person` (doc) VALUES ('{"_id":"6eee6f07ab66e611564dfeeead98f1ef","name ":"Frank","where_are_you_from":"London"}')
  • 34. A classical organization with sales A complex example 34 person sales categories departments locations countries customersclass
  • 35. The classical organization as a SQL result SQL to JSON (1) select name, sale_date, sale_amount as '$$$', customer, class_name from person inner join sales using (person_id) inner join customers using (customer_id) inner join class c on (c.class_id = sales.class_id); +--------+------------+-------+-------------+------------+ | name | sale_date | $$$ | customer | class_name | +--------+------------+-------+-------------+------------+ | Frank | 2003-10-01 | 23000 | DataSmart | software | | Frank | 2003-10-12 | 45000 | NewHardware | hardware | | Frank | 2003-11-04 | 60000 | DataSmart | services | | Susan | 2003-11-02 | 25000 | ViewData | software | | Susan | 2003-10-13 | 18000 | SmartEdu | services | | Martin | 2003-10-12 | 50000 | SmartEdu | hardware | +--------+------------+-------+-------------+------------+ 35
  • 36. The classical organization as a collection of documents SQL to JSON (2) 36
  • 37. The world_x database comes with some beefy data A bigger collection mysql-js> db.getCollections() { "CountryInfo": <Collection:CountryInfo>, "person": <Collection:person> } mysql-js> ci=db.getCollection('CountryInfo') <Collection:CountryInfo> 37
  • 38. The data is in layers Sample data from world_x mysql-js> ci.find().limit(1) [ { "GNP": 828, "IndepYear": null, "Name": "Aruba", "_id": "ABW", "demographics": { "LifeExpectancy": 78.4000015258789, "Population": 103000 }, "geography": { "Continent": "North America", "Region": "Caribbean", "SurfaceArea": 193 }, "government": { "GovernmentForm": "Nonmetropolitan Territory of The Netherlands", "HeadOfState": "Beatrix" } } ] 38
  • 39. Not always easy to get Complex queries are possible 39
  • 40. Since they are both schema-less ... ‣ From MySQL to MongoDB • extract data from a document store • feed it to MongoDB ‣ From MongoDB to MySQL • create collection • extract data • filter off the oddities • feed it to MySQL shell Examples: to and from MongoDB 40
  • 41. Extracting data From MySQL to Mongoldb (1) // extract.py import mysqlx import json session = mysqlx.get_session( ... ) schema = session.get_schema('world_x') collection = schema.get_collection('CountryInfo') result = collection.find().execute() docs = result.fetch_all() for doc in docs: doc = dict(doc) print(json.dumps(doc, indent=4)) session.close() # python extract.py > /data/country_info.json 41
  • 42. import data to mongoldb From MySQL to Mongoldb (2) mongoimport --db test --collection countries --drop --file /data/country_info.json 42
  • 43. First create the collection From MongoDB to MySQL (1) mysql-js> db.createCollection('restaurants') 43
  • 44. Export the data from MongoDB From MongoDB to MySQL (2) docker exec -ti mongo mongo --quiet --eval 'DBQuery.shellBatchSize=300; var all=db.restaurants.find() ; all' | perl -pe 's/(?:ObjectId|ISODate)(("[^"]+"))/ $1/g' > all_recs.json 44
  • 45. There is data like this: Why do we need to filter { "_id" : ObjectId("57b81d385957bb0d60511ce5"), "borough" : "Bronx", "cuisine" : "Bakery", "grades" : [ { "date" : ISODate("2014-03-03T00:00:00Z"), "grade" : "A", "score" : 2 }, ], "name" : "Morris Park Bake Shop", "restaurant_id" : "30075445" } 45
  • 46. Importing into MySQL schema = session.get_schema('test') collection = schema.create_collection('restaurants') with open('all_recs.json', 'r') as json_data: for line in json_data: skip=re.match('Type', line) if not skip: rec = json.loads(line) collection.add(rec).execute() 46
  • 47. What's a MySQL Document? A look inside ‣ mysqlsh calls it a "collection" ‣ mysql calls it a table • with a GENERATED _id field • with a json field 47
  • 48. The old client view mysql show tables; +-------------------+ | Tables_in_world_x | +-------------------+ | City | | Country | | CountryInfo | | CountryLanguage | +-------------------+ 4 rows in set (0.00 sec) 48
  • 49. The document store view mysqlsh mysql-js> db.getCollections() { "CountryInfo": <Collection:CountryInfo> } mysql-js> db.getTables() { "City": <Table:City>, "Country": <Table:Country>, "CountryLanguage": <Table:CountryLanguage> } 49
  • 50. The old client view mysql show create table CountryInfoG ******* 1. row *************************** Table: CountryInfo Create Table: CREATE TABLE `CountryInfo` ( `doc` json DEFAULT NULL, `_id` varchar(32) GENERATED ALWAYS AS (json_unquote(json_extract(`doc`,'$._id'))) STORED ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) 50
  • 51. The "truth" general log SELECT C.table_name AS name, IF(ANY_VALUE(T.table_type)='VIEW', 'VIEW', IF(COUNT(*) = COUNT(CASE WHEN (column_name = 'doc' AND data_type = 'json') THEN 1 ELSE NULL END) + COUNT(CASE WHEN (column_name = '_id' AND generation_expression = 'json_unquote(json_extract(`doc`,''$._id''))') THEN 1 ELSE NULL END) + COUNT(CASE WHEN (column_name != '_id' AND generation_expression RLIKE '^(json_unquote[[. (.]])?json_extract[[.(.]]`doc`,''[[.$.]]([[...]] [^[:space:][...]]+)+''[[.).]]{1,2}$') THEN 1 ELSE NULL END), 'COLLECTION', 'TABLE')) AS type FROM information_schema.columns AS C LEFT JOIN information_schema.tables AS T USING (table_name)WHERE C.table_schema = 'world_x' GROUP BY C.table_name ORDER BY C.table_name 51
  • 52. I'd say it needs more integration how x-plugin finds "collections" SELECT C.table_name AS name, IF(ANY_VALUE(T.table_type)='VIEW', 'VIEW', IF(COUNT(*) = COUNT(CASE WHEN (column_name = 'doc' AND data_type = 'json') THEN 1 ELSE NULL END) + COUNT(CASE WHEN (column_name = '_id' AND generation_expression = 'json_unquote(json_extract(`doc`,''$._id''))') THEN 1 ELSE NULL END) + COUNT(CASE WHEN (column_name != '_id' AND generation_expression RLIKE '^(json_unquote[[. (.]])?json_extract[[.(.]]`doc`,''[[.$.]]([[...]][^[:space:][...]]+)+''[[.).]] {1,2}$') THEN 1 ELSE NULL END), 'COLLECTION', 'TABLE')) AS type FROM information_schema.columns AS C LEFT JOIN information_schema.tables AS T USING (table_name)WHERE C.table_schema = 'world_x' GROUP BY C.table_name ORDER BY C.table_name +-----------------+------------+ | name | type | +-----------------+------------+ | City | TABLE | | Country | TABLE | | CountryInfo | COLLECTION | | CountryLanguage | TABLE | +-----------------+------------+ 52
  • 53. A few tricks that could be useful More with mysql shell ‣ Using mysqlsh to export in JSON format from regular MySQL tables ‣ Running mysqlsh in Docker without a dedicated container. 53
  • 54. where to find the examples used in this presentation Examples https://github.com/datacharmer/mysql-document-store 54