SlideShare una empresa de Scribd logo
1 de 78
Descargar para leer sin conexión
MySQL Cookbook
Recipes for Your Business
Sveta Smirnova
Principal Support Engineering Coordinator
l
Sveta Smirnova
• MySQL Support Engineer
• Author
MySQL Troubleshooting
MySQL Cookbook, 4th Edition
• JSON UDF functions
• FILTER clause for MySQL
• Speaker
• Percona Live, OOW, Fosdem,
DevConf, HighLoad...
Sveta the Speaker
• Audience: DBAs
• They do not write queries
• They tune
• Server options
• Indexes
• Table structure
3
MySQL Cookbook by O’Reilly
• For developers
• New topic for me → challenging
• In past I worked as a developer
4
MySQL Cookbook by O’Reilly
• For developers
• New topic for me → challenging
• In past I worked as a developer
• I accepted
5
15 years ago
• Queries
sql = "SELECT name, lastname " +
"FROM my_table " +
"WHERE id = " + my_id
6
15 years ago
• Placeholders
sql = "SELECT name, lastname " +
"FROM my_table " +
"WHERE id = ?"
7
15 years ago
• ORM
Speaker(name="Sveta", lastname="Smirnova").save()
8
Was anything changed?
• Nothing
9
Was anything changed?
• Nothing
• New MySQL APIs
• Document Store support in MySQL
• Object-oriented query language in MySQL X
DevAPI
10
Our Topics Today
11
MySQL CLI
mysql > SELECT ’Hello, world!’;
+---------------+
| Hello, world! |
+---------------+
| Hello, world! |
+---------------+
1 row in set (0,00 sec)
12
MySQL CLI
• Your SQL code debugger
• Tested by
• Millions of users
• MySQL developers
• Hundreds of tests at every release
• Model API for your query
13
MySQL Shell
MySQL JS > print("Hello, world!")
Hello, world!
MySQL JS > py
Switching to Python mode...
MySQL Py > print("Hello, world!")
Hello, world!
MySQL Py > sql
Switching to SQL mode... Commands end with ;
MySQL SQL > SELECT ’Hello, world!’;
+---------------+
| Hello, world! |
+---------------+
| Hello, world! |
+---------------+
1 row in set (0.0003 sec)
14
MySQL Shell
• New command-line client with X DevAPI support
• SQL and Object-Oriented queries
• MySQL Server administration
• Utilities
• Replication
• InnoDB Cluster
• Your own applications
15
X DevAPI
• Asynchronous code execution
• Works with MySQL
• As usual: by executing SQL
• Querying tables as documents
• Collections and documents support
Data storage in JSON
NoSQL-syntax, similar to MongoDB’s
16
Reading
Standard SQL
SQL > SELECT thing, SUM(legs+arms) AS limbs
-> FROM limbs GROUP BY thing
-> HAVING limbs > 5;
+-----------+-------+
| thing | limbs |
+-----------+-------+
| armchair | 6 |
| centipede | 99 |
| insect | 6 |
| squid | 10 |
+-----------+-------+
4 rows in set (0.0004 sec)
17
Reading
X DevAPI for tables
JS > session.getCurrentSchema().
-> getTable(’limbs’).
-> select().groupBy(’thing’).
-> having(’SUM(legs + arms) > 5’)
->
+-----------+------+------+
| thing | legs | arms |
+-----------+------+------+
| armchair | 4 | 2 |
| centipede | 99 | 0 |
| insect | 6 | 0 |
| squid | 0 | 10 |
+-----------+------+------+
4 rows in set (0.0005 sec)
18
Reading
Document Store
Py > session.get_current_schema().
get_collection(’collectionLimbs’).
find(’IFNULL(arms, 0) + IFNULL(legs, 0) > 5’)
{"_id":"000061ed7c240000000000000002",
"arms":0,"legs":6,"thing":"insect"}
{"_id":"000061ed7c240000000000000003",
"arms":10,"legs":0,"thing":"squid"}
{"_id":"000061ed7c240000000000000005",
"arms":0,"legs":99,"thing":"centipede"}
{"_id":"000061ed7c240000000000000007",
"arms":2,"legs":4,"thing":"armchair"}
4 documents in set (0.0004 sec)
19
Reading
Tables and Document Store
JS > session.getCurrentSchema().
-> getCollectionAsTable(’collectionLimbs’).
-> select(’JSON_EXTRACT(doc, "$.thing") AS thing’,
-> ’SUM(IFNULL(JSON_EXTRACT(doc, "$.arms"), 0) +
-> IFNULL(JSON_EXTRACT(doc, "$.legs"), 0)) AS limbs’).
-> groupBy(’thing’).having(’limbs > 5’)
->
+-------------+-------+
| thing | limbs |
+-------------+-------+
| "insect" | 6 |
| "squid" | 10 |
| "centipede" | 99 |
| "armchair" | 6 |
+-------------+-------+
4 rows in set (0.0006 sec)
20
Working with Results
SQL code in Python
cursor = conn.cursor()
cursor.execute("SELECT id, name, cats FROM profile")
while True:
row = cursor.fetchone()
if row is None:
break
print(f"id: row[0], name: row[1], cats: row[2]")
21
Working with Results
X DevAPI for tables
result = session.get_schema(’cookbook’).
get_table(’profile’).
select(’id’, ’name’, ’cats’).execute()
while True:
row = result.fetch_one()
if row is None:
break
print(f"id: row[0], name: row[1], cats: row[2]")
22
Working with Results
Document Store
result = session.get_schema(’cookbook’).
get_collection(’collectionProfile’).
find().execute()
while True:
doc = result.fetch_one()
if doc is None:
break
print(f"id: doc[’id’], name: doc[’name’], cats: doc[’cats’]")
23
Working with Results
Tables and Document Store
result = session.get_schema(’cookbook’).
get_collection_as_table(’collectionProfile’).
select(’JSON_EXTRACT(doc, "$.id") AS id’).
select(’JSON_EXTRACT(doc, "$.name") AS name’).
select(’JSON_EXTRACT(doc, "$.cats") AS cats’).execute()
while True:
row = result.fetch_one()
if row is None:
break
print(f"id: row[0], name: row[1], cats: row[2]")
24
Changing Data
Standard SQL
INSERT INTO limbs(thing, legs, arms)
VALUES(’cat’, 2, 2);
25
Changing Data
X DevAPI for tables
JS > session.getSchema(’cookbook’).
-> getTable(’limbs’).
-> update().
-> set(’legs’, 4).
-> set(’arms’, 0).
-> where(’thing = "cat"’)
->
26
Changing Data
Document Store
Py > session.get_schema(’cookbook’).
get_collection(’collectionLimbs’).
add_or_replace_one(’00006002f065000000000000006b’,
{"thing": "cat", "legs": 4, "arms": 0})
27
Changing Data
Tables and Document Store
JS > session.getSchema(’cookbook’).
-> getCollectionAsTable(’collectionLimbs’).
-> delete().
-> where(’JSON_EXTRACT(doc, "$.thing") = "cat"’)
->
28
Character Encoding
Standard API: establishing connection
conn_params = {
"database": "test",
"host": "localhost",
"user": "sveta",
"password": "",
"charset": "cp1251"
}
conn = mysql.connector.connect(**conn_params)
29
Character Encoding
Standard API: SET NAMES
cursor.execute("SET NAMES utf8mb4")
30
Character Encoding
• X DevAPI
• Only utf8mb4
May not work with your connector!
31
Generating Summaries
• When was the longest trip per driver?
+--------+-------+------------+-------+
| rec_id | name | trav_date | miles |
+--------+-------+------------+-------+
| 1 | Ben | 2014-07-30 | 152 |
| 2 | Suzi | 2014-07-29 | 391 |
| 3 | Henry | 2014-07-29 | 300 |
| 4 | Henry | 2014-07-27 | 96 |
| 5 | Ben | 2014-07-29 | 131 |
| 6 | Henry | 2014-07-26 | 115 |
| 7 | Suzi | 2014-08-02 | 502 |
| 8 | Henry | 2014-08-01 | 197 |
| 9 | Ben | 2014-08-02 | 79 |
| 10 | Henry | 2014-07-30 | 203 |
+--------+-------+------------+-------+
32
Generating Summaries
Naive solution
mysql> SELECT name, trav_date, MAX(miles) AS ’longest trip’
-> FROM driver_log GROUP BY name;
ERROR 1055 (42000): ’cookbook.driver_log.trav_date’ isn’t in GROUP BY
mysql> SET sql_mode=”;
Query OK, 0 rows affected (0,00 sec)
mysq> SELECT name, trav_date, MAX(miles) AS ’longest trip’
-> FROM driver_log GROUP BY name;
+-------+------------+--------------+
| name | trav_date | longest trip |
+-------+------------+--------------+
| Ben | 2014-07-30 | 152 |
| Suzi | 2014-07-29 | 502 |
| Henry | 2014-07-29 | 300 |
+-------+------------+--------------+
3 rows in set (0,00 sec)
33
Generating Summaries
Legacy solution
mysql> CREATE TEMPORARY TABLE t
-> SELECT name, MAX(miles) AS miles
-> FROM driver_log GROUP BY name;
mysql> SELECT d.name, d.trav_date, d.miles AS ’longest trip’
-> FROM driver_log AS d INNER JOIN t USING (name, miles)
-> ORDER BY name;
+-------+------------+--------------+
| name | trav_date | longest trip |
+-------+------------+--------------+
| Ben | 2014-07-30 | 152 |
| Henry | 2014-07-29 | 300 |
| Suzi | 2014-08-02 | 502 |
+-------+------------+--------------+
mysql> DROP TABLE t;
34
Generating Summaries
Common Table Expression (CTE)
mysql> WITH t AS
-> (SELECT name, MAX(miles) AS miles
-> FROM driver_log GROUP BY name)
-> SELECT d.name, d.trav_date, d.miles AS ’longest trip’
-> FROM driver_log AS d INNER JOIN t USING (name, miles)
-> ORDER BY name;
+-------+------------+--------------+
| name | trav_date | longest trip |
+-------+------------+--------------+
| Ben | 2014-07-30 | 152 |
| Henry | 2014-07-29 | 300 |
| Suzi | 2014-08-02 | 502 |
+-------+------------+--------------+
3 rows in set (0.01 sec)
35
Storing Errors with Diagnostic Area
Foreign keys
ALTER TABLE movies_actors_link ADD FOREIGN KEY(movie_id) REFERENCES movies(id);
ALTER TABLE movies_actors_link ADD FOREIGN KEY(actor_id) REFERENCES actors(id);
36
Storing Errors with Diagnostic Area
Custom error log
CREATE TABLE ‘movies_actors_log‘ (
‘err_ts‘ timestamp NULL DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP,
‘err_number‘ int DEFAULT NULL,
‘err_sqlstate‘ char(5) DEFAULT NULL,
‘err_message‘ TEXT DEFAULT NULL,
‘movie_id‘ int unsigned DEFAULT NULL,
‘actor_id‘ int unsigned DEFAULT NULL
);
37
Storing Errors with Diagnostic Area
Data modification procedure
CREATE PROCEDURE insert_movies_actors_link(movie INT, actor INT)
BEGIN
DECLARE e_number INT;
DECLARE e_sqlstate CHAR(5);
DECLARE e_message TEXT;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1
e_number = MYSQL_ERRNO, e_sqlstate = RETURNED_SQLSTATE, e_message = MESSAGE_TEXT;
INSERT INTO movies_actors_log(err_number, err_sqlstate,
err_message, movie_id, actor_id)
VALUES(e_number, e_sqlstate, e_message, movie, actor);
RESIGNAL;
END;
INSERT INTO movies_actors_link VALUES(movie, actor);
END
38
Storing Errors with Diagnostic Area
After few errors
mysql> SELECT err_ts, err_message, movie_id, actor_id
-> FROM movies_actors_logG
*************************** 1. row ***************************
err_ts: 2022-02-28 04:23:28
err_message: Cannot add or update a child row: a foreign key
constraint fails (‘cookbook‘.‘movies_actors_link‘,
CONSTRAINT ‘movies_actors_link_ibfk_1‘
FOREIGN KEY (‘movie_id‘) REFERENCES ‘movies‘ (‘id‘))
movie_id: 7
actor_id: 11
...
39
Storing Errors with Diagnostic Area
After few errors
*************************** 2. row ***************************
err_ts: 2022-02-28 04:23:38
err_message: Column ’movie_id’ cannot be null
movie_id: NULL
actor_id: 10
*************************** 3. row ***************************
err_ts: 2022-02-28 04:23:48
err_message: Duplicate entry ’6-9’ for key
’movies_actors_link.movie_id’
movie_id: 6
actor_id: 9
40
Export and Import
• Industry standard
mysqldump
MyDumper
XtraBackup
41
Export and Import
• mysqlpump: mysqldump on steroids
• Legacy commands removed
ALTER TABLE ... DISABLE KEYS
• Multithreaded
--default-parallelism
• More filters
--exclude-*
--include-*
--skip-definer
42
Export and Import
• MySQL Shell Utilities
Export into CSV
JS > util.exportTable(
-> ’limbs’, ’BACKUP/cookbook/limbs.csv’,
-> dialect: "csv-unix")
Import from CSV
Py > sql CREATE TABLE test.limbs LIKE limbs;
Fetching table and column names from ‘cookbook‘
for auto-completion...
Press ^C to stop.
Query OK, 0 rows affected (0.0264 sec)
Py > util.import_table("BACKUP/cookbook/limbs.csv",
"dialect": "csv-unix", "schema": "test")
43
Export and Import
• MySQL Shell Utilities
• Import from JSON
$ mysqlsh cbuser:cbpass@127.0.0.1:33060/cookbook 
> --import limbs.json CollectionLimbs
WARNING: Using a password on the command line interface
can be insecure.
Importing from file "limbs.json" to collection
‘cookbook‘.‘CollectionLimbs‘ in MySQL Server
at 127.0.0.1:33060
.. 11.. 11
Processed 506 bytes in 11 documents in 0.0067 sec
(11.00 documents/s)
Total successfully imported documents 11
(11.00 documents/s)
44
Export and Import
• MySQL Shell Utilities
Import from mongoexport
JS > options = {
-> "schema": "cookbook",
-> "collection": "blogs",
-> "convertBsonTypes": true
-> }
->
JS > util.importJson("blogs.json", options)
Importing from file "blogs.json" to collection
‘cookbook‘.‘blogs‘ in MySQL Server at 127.0.0.1:33060
.. 2.. 2
Processed 240 bytes in 2 documents in 0.0070 sec
(2.00 documents/s)
Total successfully imported documents 2 (2.00 documents/s)
45
Export and Import
• MySQL Shell Utilities
• Export into JSON
$ mysqlsh cbuser:cbpass@127.0.0.1:33060/cookbook 
> -e "limbs=shell.getSession().getSchema(’cookbook’).
> getCollection(’collectionLimbs’).
> find().execute().fetchAll();
> println(limbs);" > limbs.json
46
Metadata
Column metadata
def get_enumorset_info(client, db_name, tbl_name, col_name)
sth = client.prepare(
"SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? AND COLUMN_NAME = ?")
res = sth.execute(db_name, tbl_name, col_name)
return nil if res.count == 0 # no such column
row = res.first
info = {}
info["name"] = row.values[0]
return nil unless row.values[1] =~ /^(ENUM|SET)((.*))$/i
info["type"] = $1
info["values"] = $2.split(",").collect |val| val.sub(/^’(.*)’$/, "1")
info["nullable"] = (row.values[2].upcase == "YES")
info["default"] = row.values[3]
return info
end
47
Metadata
Checking in the application
info = get_enumorset_info(conn, db_name, tbl_name, col_name)
if info is not None and info[’type’].upper() == ’ENUM’:
valid = 1 if list(map(lambda v: v.upper(), info[’values’])).count(val.upper()) > 0 else 0
48
Metadata
All tables, referenced by foreign keys
mysql> SELECT ku.TABLE_NAME AS child,
-> ku.REFERENCED_TABLE_NAME AS parent
-> FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
-> JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ku
-> USING (CONSTRAINT_NAME, TABLE_SCHEMA, TABLE_NAME)
-> WHERE CONSTRAINT_TYPE=’FOREIGN KEY’ AND
-> ku.TABLE_SCHEMA=’cookbook’;
+--------------------+--------+
| child | parent |
+--------------------+--------+
| movies_actors_link | movies |
| movies_actors_link | actors |
+--------------------+--------+
2 rows in set (0,00 sec)
49
Metadata
Result: standard API
cursor = conn.cursor(buffered=True)
cursor.execute(stmt)
# metadata information becomes available at this point ...
print("Number of rows: %d" % cursor.rowcount)
if cursor.with_rows:
ncols = len(cursor.description)
else:
ncols = 0 # no result set
print("Number of columns: %d" % ncols)
if ncols == 0:
print("Note: statement has no result set")
else:
for i, col_info in enumerate(cursor.description):
name, type, _, _, _, _, nullable, flags, *_ = col_info
print("--- Column %d (%s) ---" % (i, name))
...
50
Metadata
• Result: X DevAPI
• Only basic information
"executionTime": "0.0007 sec",
"affectedRowCount": 0,
"affectedItemsCount": 0,
"warningCount": 0,
"warningsCount": 0,
"warnings": [],
"info": "",
"autoIncrementValue": 0
51
Validation and Formatting
CHECK Constraints
mysql> ALTER TABLE patients ADD CONSTRAINT date_check
-> CHECK((date_departed IS NULL) OR
-> (date_departed >= date_arrived));
mysql> INSERT INTO patients (national_id, name, surname,
-> gender, age, diagnosis, date_arrived, date_departed)
-> VALUES(’34GD429520’, ’John’, ’Doe’, ’M’, 45,
-> ’Data Phobia’, ’2020-07-20’, ’2020-05-31’);
ERROR 3819 (HY000): Check constraint ’date_check’ is violated.
52
Validation and Formatting
JSON Schema for collections
JS > schema={
-> "$schema": "http://json-schema.org/draft-07/schema",
-> "id": "http://example.com/cookbook.json",
-> "type": "object",
-> "description": "Table limbs as a collection",
-> "properties": {
-> "thing": {"type": "string"},
-> "legs": {
-> "anyOf": [{"type": "number"},{"type": "null"}],
-> "default": 0
-> },
-> "arms": {
-> "anyOf": [{"type": "number"},{"type": "null"}],
-> "default": 0
-> }},
-> "required": ["thing","legs","arms"] }
53
Validation and Formatting
JS > collectionLimbs=session.getCurrentSchema().
-> createCollection(’collectionLimbs’,
-> {"validation": {"level": "strict", "schema": schema}})
->
54
Sequences
Enumerating result
mysql> SELECT
-> ROW_NUMBER() OVER win AS turn,
-> first_name, last_name FROM name
-> WINDOW win
-> AS (ORDER BY RAND());
+------+------------+-----------+
| turn | first_name | last_name |
+------+------------+-----------+
| 1 | Devon | White |
| 2 | Kevin | Brown |
| 3 | Rondell | White |
| 4 | Vida | Blue |
| 5 | Pete | Gray |
+------+------------+-----------+
5 rows in set (0.00 sec)
55
Sequences
Several sequences in one query
mysql> WITH RECURSIVE sequences(id, geo, random) AS
-> (SELECT 1, 3, FLOOR(1+RAND()*5)
-> UNION ALL
-> SELECT id + 1, geo * 4, FLOOR(1+RAND()*5) FROM sequences WHERE id < 5)
-> SELECT * FROM sequences;
+------+------+--------+
| id | geo | random |
+------+------+--------+
| 1 | 3 | 4 |
| 2 | 12 | 4 |
| 3 | 48 | 2 |
| 4 | 192 | 2 |
| 5 | 768 | 3 |
+------+------+--------+
5 rows in set (0.00 sec)
56
Joins and Subqueries
How many drivers on the road?
mysql> SELECT trav_date, COUNT(trav_date) AS drivers
-> FROM driver_log GROUP BY trav_date ORDER BY trav_date;
+------------+---------+
| trav_date | drivers |
+------------+---------+
| 2014-07-26 | 1 |
| 2014-07-27 | 1 |
| 2014-07-29 | 3 |
| 2014-07-30 | 2 |
| 2014-08-01 | 1 |
| 2014-08-02 | 2 |
+------------+---------+
57
Joins and Subqueries
Missed dates
mysql> CREATE TABLE dates (d DATE);
-> INSERT INTO dates (d)
-> VALUES(’2014-07-26’),(’2014-07-27’),(’2014-07-28’),
-> (’2014-07-29’),(’2014-07-30’),(’2014-07-31’),
-> (’2014-08-01’),(’2014-08-02’);
58
Joins and Subqueries
When drivers have rest?
mysql> SELECT dates.d
-> FROM dates LEFT JOIN driver_log
-> ON dates.d = driver_log.trav_date
-> WHERE driver_log.trav_date IS NULL;
+------------+
| d |
+------------+
| 2014-07-28 |
| 2014-07-31 |
+------------+
59
Joins and Subqueries
CTE: in one query
WITH RECURSIVE dates (d) AS (
SELECT ’2014-07-26’
UNION ALL
SELECT d + INTERVAL 1 day
FROM dates
WHERE d < ’2014-08-02’)
SELECT dates.d, COUNT(driver_log.trav_date) AS drivers
FROM dates LEFT JOIN driver_log
ON dates.d = driver_log.trav_date
GROUP BY d ORDER BY d;
60
Statistics
Ranking: legacy way
mysql> SET @rownum := 0;
Query OK, 0 rows affected (0,00 sec)
mysql> SELECT @rownum := @rownum + 1 AS ‘rank‘, score FROM ranks ORDER BY score DESC;
+------+-------+
| rank | score |
+------+-------+
| 1 | 5 |
| 2 | 4 |
| 3 | 4 |
| 4 | 3 |
| 5 | 2 |
| 6 | 2 |
| 7 | 2 |
| 8 | 1 |
+------+-------+
8 rows in set, 1 warning (0,00 sec)
61
Statistics
The issue!
mysql> SHOW WARNINGSG
*************************** 1. row ***************************
Level: Warning
Code: 1287
Message: Setting user variables within expressions is
deprecated and will be removed in a future release. Consider
alternatives: ’SET variable=expression, ...’, or
’SELECT expression(s) INTO variables(s)’.
1 row in set (0,00 sec)
62
Statistics
Ranking: Window Functions
mysql> SELECT ROW_NUMBER() OVER win AS ’rank’, score
-> FROM ranks WINDOW win AS (ORDER BY score DESC);
+------+-------+
| rank | score |
+------+-------+
| 1 | 5 |
| 2 | 4 |
| 3 | 4 |
| 4 | 3 |
| 5 | 2 |
| 6 | 2 |
| 7 | 2 |
| 8 | 1 |
+------+-------+
8 rows in set (0,00 sec)
63
Statistics
Repeating results
mysql> SELECT ROW_NUMBER() OVER win AS ’row’,
-> RANK() OVER win AS ’rank’,
-> score FROM ranks WINDOW win AS (ORDER BY score DESC);
+------+------+-------+
| row | rank | score |
+------+------+-------+
| 1 | 1 | 5 |
| 2 | 2 | 4 |
| 3 | 2 | 4 |
| 4 | 4 | 3 |
| 5 | 5 | 2 |
| 6 | 5 | 2 |
| 7 | 5 | 2 |
| 8 | 8 | 1 |
+------+------+-------+
64
Duplicates
Duplicate users
mysql> WITH tmp AS (
-> SELECT COUNT(*) AS count, last_name, first_name
-> FROM catalog_list GROUP BY last_name, first_name HAVING count > 1)
-> SELECT catalog_list.*
-> FROM tmp INNER JOIN catalog_list USING (last_name, first_name)
-> ORDER BY last_name, first_name;
+-----------+------------+----------------------+
| last_name | first_name | street |
+-----------+------------+----------------------+
| Baxter | Wallace | 57 3rd Ave. |
| BAXTER | WALLACE | 57 3rd Ave. |
| Baxter | Wallace | 57 3rd Ave., Apt 102 |
| Pinter | Marlene | 9 Sunset Trail |
| Pinter | Marlene | 9 Sunset Trail |
+-----------+------------+----------------------+
5 rows in set (0,00 sec)
65
JSON
• Data type JSON
• Compact storage
• In-place update
On the source and replica
binlog_row_value_options=PARTIAL_JSON
• Operators -> and ->>
• Functions
Search, pattern support
Update
Validation, including JSON schema
Conversion
Documents join
66
JSON
• JSON Path for queries
Names of book authors
mysql> SELECT JSON_EXTRACT(author, ’$.name’) AS author
-> FROM book_authors;
+---------+
| author |
+---------+
| "Paul" |
| "Alkin" |
| "Sveta" |
+---------+
3 rows in set (0,00 sec)
67
JSON
• JSON Path for queries
Names of book authors
mysql> SELECT author->’$.name’ AS author
-> FROM book_authors;
+---------+
| author |
+---------+
| "Paul" |
| "Alkin" |
| "Sveta" |
+---------+
3 rows in set (0,00 sec)
68
JSON
• JSON Path for queries
Removing quotes
mysql> SELECT JSON_UNQUOTE(
-> JSON_EXTRACT(author, ’$.name’)
-> ) AS author FROM book_authors;
+--------+
| author |
+--------+
| Paul |
| Alkin |
| Sveta |
+--------+
3 rows in set (0,00 sec)
69
JSON
• JSON Path for queries
Removing quotes
mysql> SELECT author-»’$.name’ AS author
-> FROM book_authors;
+--------+
| author |
+--------+
| Paul |
| Alkin |
| Sveta |
+--------+
3 rows in set (0,00 sec)
70
JSON
• JSON Path for queries
First and last books
mysql> SELECT CONCAT(author-»’$.name’, ’ ’, author-»’$.lastname’) AS author,
-> author-»’$.books[0]’ AS ‘First Book‘, author-»’$.books[last]’ AS ‘Last Book‘
-> FROM book_authorsG
************************ 1. row ************************
author: Paul DuBois
First Book: Software Portability with imake: ...
Last Book: MySQL (Developer’s Library)
************************ 2. row ************************
author: Alkin Tezuysal
First Book: MySQL Cookbook
Last Book: MySQL Cookbook
************************ 3. row ************************
author: Sveta Smirnova
First Book: MySQL Troubleshooting
Last Book: MySQL Cookbook
71
JSON
Indexes
mysql> ALTER TABLE book_authors
-> ADD COLUMN lastname VARCHAR(255)
-> GENERATED ALWAYS AS
-> (JSON_UNQUOTE(JSON_EXTRACT(author, ’$.lastname’)));
mysql> ALTER TABLE book_authors
-> ADD COLUMN name VARCHAR(255)
-> GENERATED ALWAYS AS (author-»’$.name’);
mysql> CREATE INDEX author_name
-> ON book_authors(lastname, name);
72
Transactions
Standard API
conn.start_transaction()
cursor = conn.cursor()
# move some money from one person to the other
cursor.execute("UPDATE money SET amt = amt - 6
WHERE name = ’Eve’")
cursor.execute("UPDATE money SET amt = amt + 6
WHERE name = ’Ida’")
cursor.close()
conn.commit()
73
Transactions
X DevAPI for tables
session.get_schema(’cookbook’).get_table(’money’)
session.start_transaction()
money.update().set(’amt’, 4).where("name = ’Eve’").execute()
money.update().set(’amt’, 10).where("name = ’Ida’").execute()
session.commit()
74
Transactions
Document Store
money = session.get_schema(’cookbook’).get_collection(’collectionMoney’)
session.start_transaction()
Eve = money.find("name = ’Eve’").execute().fetch_one()
Ida = money.find("name = ’Ida’").execute().fetch_one()
Eve.amt = Eve.amt - 6
Ida.amt = Ida.amt + 6
money.replace_one(Eve._id, Eve)
money.replace_one(Ida._id, Ida)
session.commit()
75
More Information
X DevAPI
X Protocol
MySQL Shell
Common Table Expressions
Window functions
JSON functions
76
Thank you!
www.slideshare.net/SvetaSmirnova
twitter.com/svetsmirnova
github.com/svetasmirnova
77
MySQL Cookbook: Recipes for Your Business

Más contenido relacionado

La actualidad más candente

Understanding my database through SQL*Plus using the free tool eDB360
Understanding my database through SQL*Plus using the free tool eDB360Understanding my database through SQL*Plus using the free tool eDB360
Understanding my database through SQL*Plus using the free tool eDB360
Carlos Sierra
 
MySQL Performance Schema in 20 Minutes
 MySQL Performance Schema in 20 Minutes MySQL Performance Schema in 20 Minutes
MySQL Performance Schema in 20 Minutes
Sveta Smirnova
 

La actualidad más candente (20)

MySQL Database Architectures - InnoDB ReplicaSet & Cluster
MySQL Database Architectures - InnoDB ReplicaSet & ClusterMySQL Database Architectures - InnoDB ReplicaSet & Cluster
MySQL Database Architectures - InnoDB ReplicaSet & Cluster
 
The Proxy Wars - MySQL Router, ProxySQL, MariaDB MaxScale
The Proxy Wars - MySQL Router, ProxySQL, MariaDB MaxScaleThe Proxy Wars - MySQL Router, ProxySQL, MariaDB MaxScale
The Proxy Wars - MySQL Router, ProxySQL, MariaDB MaxScale
 
Migration to ClickHouse. Practical guide, by Alexander Zaitsev
Migration to ClickHouse. Practical guide, by Alexander ZaitsevMigration to ClickHouse. Practical guide, by Alexander Zaitsev
Migration to ClickHouse. Practical guide, by Alexander Zaitsev
 
Troubleshooting tips and tricks for Oracle Database Oct 2020
Troubleshooting tips and tricks for Oracle Database Oct 2020Troubleshooting tips and tricks for Oracle Database Oct 2020
Troubleshooting tips and tricks for Oracle Database Oct 2020
 
Highly efficient backups with percona xtrabackup
Highly efficient backups with percona xtrabackupHighly efficient backups with percona xtrabackup
Highly efficient backups with percona xtrabackup
 
MySQL Administrator 2021 - 네오클로바
MySQL Administrator 2021 - 네오클로바MySQL Administrator 2021 - 네오클로바
MySQL Administrator 2021 - 네오클로바
 
Tanel Poder - Troubleshooting Complex Oracle Performance Issues - Part 2
Tanel Poder - Troubleshooting Complex Oracle Performance Issues - Part 2Tanel Poder - Troubleshooting Complex Oracle Performance Issues - Part 2
Tanel Poder - Troubleshooting Complex Oracle Performance Issues - Part 2
 
State transfer With Galera
State transfer With GaleraState transfer With Galera
State transfer With Galera
 
ProxySQL for MySQL
ProxySQL for MySQLProxySQL for MySQL
ProxySQL for MySQL
 
Building Stream Infrastructure across Multiple Data Centers with Apache Kafka
Building Stream Infrastructure across Multiple Data Centers with Apache KafkaBuilding Stream Infrastructure across Multiple Data Centers with Apache Kafka
Building Stream Infrastructure across Multiple Data Centers with Apache Kafka
 
ProxySQL on Kubernetes
ProxySQL on KubernetesProxySQL on Kubernetes
ProxySQL on Kubernetes
 
Innodb Deep Talk #2 でお話したスライド
Innodb Deep Talk #2 でお話したスライドInnodb Deep Talk #2 でお話したスライド
Innodb Deep Talk #2 でお話したスライド
 
Understanding my database through SQL*Plus using the free tool eDB360
Understanding my database through SQL*Plus using the free tool eDB360Understanding my database through SQL*Plus using the free tool eDB360
Understanding my database through SQL*Plus using the free tool eDB360
 
The MySQL Query Optimizer Explained Through Optimizer Trace
The MySQL Query Optimizer Explained Through Optimizer TraceThe MySQL Query Optimizer Explained Through Optimizer Trace
The MySQL Query Optimizer Explained Through Optimizer Trace
 
MySQL Performance Schema in 20 Minutes
 MySQL Performance Schema in 20 Minutes MySQL Performance Schema in 20 Minutes
MySQL Performance Schema in 20 Minutes
 
MySQL Performance Schema in Action: the Complete Tutorial
MySQL Performance Schema in Action: the Complete TutorialMySQL Performance Schema in Action: the Complete Tutorial
MySQL Performance Schema in Action: the Complete Tutorial
 
Oracle Performance Tuning Fundamentals
Oracle Performance Tuning FundamentalsOracle Performance Tuning Fundamentals
Oracle Performance Tuning Fundamentals
 
MySQL GTID 시작하기
MySQL GTID 시작하기MySQL GTID 시작하기
MySQL GTID 시작하기
 
Oracle Real Application Clusters 19c- Best Practices and Internals- EMEA Tour...
Oracle Real Application Clusters 19c- Best Practices and Internals- EMEA Tour...Oracle Real Application Clusters 19c- Best Practices and Internals- EMEA Tour...
Oracle Real Application Clusters 19c- Best Practices and Internals- EMEA Tour...
 
ClickHouse Query Performance Tips and Tricks, by Robert Hodges, Altinity CEO
ClickHouse Query Performance Tips and Tricks, by Robert Hodges, Altinity CEOClickHouse Query Performance Tips and Tricks, by Robert Hodges, Altinity CEO
ClickHouse Query Performance Tips and Tricks, by Robert Hodges, Altinity CEO
 

Similar a MySQL Cookbook: Recipes for Your Business

Cat database
Cat databaseCat database
Cat database
tubbeles
 
Mysqlfunctions
MysqlfunctionsMysqlfunctions
Mysqlfunctions
N13M
 
Applied Partitioning And Scaling Your Database System Presentation
Applied Partitioning And Scaling Your Database System PresentationApplied Partitioning And Scaling Your Database System Presentation
Applied Partitioning And Scaling Your Database System Presentation
Richard Crowley
 
අරුණ හේරත්_MYSQL සිංහල_TL_I_033__techlogiclk.com.pdf
අරුණ හේරත්_MYSQL සිංහල_TL_I_033__techlogiclk.com.pdfඅරුණ හේරත්_MYSQL සිංහල_TL_I_033__techlogiclk.com.pdf
අරුණ හේරත්_MYSQL සිංහල_TL_I_033__techlogiclk.com.pdf
AnilManage
 

Similar a MySQL Cookbook: Recipes for Your Business (20)

MySQL Cookbook: Recipes for Developers, Alkin Tezuysal and Sveta Smirnova - P...
MySQL Cookbook: Recipes for Developers, Alkin Tezuysal and Sveta Smirnova - P...MySQL Cookbook: Recipes for Developers, Alkin Tezuysal and Sveta Smirnova - P...
MySQL Cookbook: Recipes for Developers, Alkin Tezuysal and Sveta Smirnova - P...
 
MySQL Cookbook: Recipes for Developers
MySQL Cookbook: Recipes for DevelopersMySQL Cookbook: Recipes for Developers
MySQL Cookbook: Recipes for Developers
 
Modern query optimisation features in MySQL 8.
Modern query optimisation features in MySQL 8.Modern query optimisation features in MySQL 8.
Modern query optimisation features in MySQL 8.
 
Percona Live 4/15/15: Transparent sharding database virtualization engine (DVE)
Percona Live 4/15/15: Transparent sharding database virtualization engine (DVE)Percona Live 4/15/15: Transparent sharding database virtualization engine (DVE)
Percona Live 4/15/15: Transparent sharding database virtualization engine (DVE)
 
My sql1
My sql1My sql1
My sql1
 
Introduction databases and MYSQL
Introduction databases and MYSQLIntroduction databases and MYSQL
Introduction databases and MYSQL
 
PHP mysql Introduction database
 PHP mysql  Introduction database PHP mysql  Introduction database
PHP mysql Introduction database
 
MySQL Kitchen : spice up your everyday SQL queries
MySQL Kitchen : spice up your everyday SQL queriesMySQL Kitchen : spice up your everyday SQL queries
MySQL Kitchen : spice up your everyday SQL queries
 
Modern solutions for modern database load: improvements in the latest MariaDB...
Modern solutions for modern database load: improvements in the latest MariaDB...Modern solutions for modern database load: improvements in the latest MariaDB...
Modern solutions for modern database load: improvements in the latest MariaDB...
 
Mysql basics1
Mysql basics1Mysql basics1
Mysql basics1
 
My SQL
My SQLMy SQL
My SQL
 
Ten Reasons Why You Should Prefer PostgreSQL to MySQL
Ten Reasons Why You Should Prefer PostgreSQL to MySQLTen Reasons Why You Should Prefer PostgreSQL to MySQL
Ten Reasons Why You Should Prefer PostgreSQL to MySQL
 
Hanya contoh saja dari xampp
Hanya contoh saja dari xamppHanya contoh saja dari xampp
Hanya contoh saja dari xampp
 
SunshinePHP 2017 - Making the most out of MySQL
SunshinePHP 2017 - Making the most out of MySQLSunshinePHP 2017 - Making the most out of MySQL
SunshinePHP 2017 - Making the most out of MySQL
 
Cat database
Cat databaseCat database
Cat database
 
Mysqlfunctions
MysqlfunctionsMysqlfunctions
Mysqlfunctions
 
Applied Partitioning And Scaling Your Database System Presentation
Applied Partitioning And Scaling Your Database System PresentationApplied Partitioning And Scaling Your Database System Presentation
Applied Partitioning And Scaling Your Database System Presentation
 
MySQL SQL Tutorial
MySQL SQL TutorialMySQL SQL Tutorial
MySQL SQL Tutorial
 
අරුණ හේරත්_MYSQL සිංහල_TL_I_033__techlogiclk.com.pdf
අරුණ හේරත්_MYSQL සිංහල_TL_I_033__techlogiclk.com.pdfඅරුණ හේරත්_MYSQL සිංහල_TL_I_033__techlogiclk.com.pdf
අරුණ හේරත්_MYSQL සිංහල_TL_I_033__techlogiclk.com.pdf
 
MySQLinsanity
MySQLinsanityMySQLinsanity
MySQLinsanity
 

Más de Sveta Smirnova

MySQL Test Framework для поддержки клиентов и верификации багов
MySQL Test Framework для поддержки клиентов и верификации баговMySQL Test Framework для поддержки клиентов и верификации багов
MySQL Test Framework для поддержки клиентов и верификации багов
Sveta Smirnova
 
How to Avoid Pitfalls in Schema Upgrade with Percona XtraDB Cluster
How to Avoid Pitfalls in Schema Upgrade with Percona XtraDB ClusterHow to Avoid Pitfalls in Schema Upgrade with Percona XtraDB Cluster
How to Avoid Pitfalls in Schema Upgrade with Percona XtraDB Cluster
Sveta Smirnova
 
Современному хайлоду - современные решения: MySQL 8.0 и улучшения Percona
Современному хайлоду - современные решения: MySQL 8.0 и улучшения PerconaСовременному хайлоду - современные решения: MySQL 8.0 и улучшения Percona
Современному хайлоду - современные решения: MySQL 8.0 и улучшения Percona
Sveta Smirnova
 

Más de Sveta Smirnova (20)

MySQL 2024: Зачем переходить на MySQL 8, если в 5.х всё устраивает?
MySQL 2024: Зачем переходить на MySQL 8, если в 5.х всё устраивает?MySQL 2024: Зачем переходить на MySQL 8, если в 5.х всё устраивает?
MySQL 2024: Зачем переходить на MySQL 8, если в 5.х всё устраивает?
 
Database in Kubernetes: Diagnostics and Monitoring
Database in Kubernetes: Diagnostics and MonitoringDatabase in Kubernetes: Diagnostics and Monitoring
Database in Kubernetes: Diagnostics and Monitoring
 
MySQL Database Monitoring: Must, Good and Nice to Have
MySQL Database Monitoring: Must, Good and Nice to HaveMySQL Database Monitoring: Must, Good and Nice to Have
MySQL Database Monitoring: Must, Good and Nice to Have
 
MySQL Performance for DevOps
MySQL Performance for DevOpsMySQL Performance for DevOps
MySQL Performance for DevOps
 
MySQL Test Framework для поддержки клиентов и верификации багов
MySQL Test Framework для поддержки клиентов и верификации баговMySQL Test Framework для поддержки клиентов и верификации багов
MySQL Test Framework для поддержки клиентов и верификации багов
 
Introduction into MySQL Query Tuning for Dev[Op]s
Introduction into MySQL Query Tuning for Dev[Op]sIntroduction into MySQL Query Tuning for Dev[Op]s
Introduction into MySQL Query Tuning for Dev[Op]s
 
Производительность MySQL для DevOps
 Производительность MySQL для DevOps Производительность MySQL для DevOps
Производительность MySQL для DevOps
 
MySQL Performance for DevOps
MySQL Performance for DevOpsMySQL Performance for DevOps
MySQL Performance for DevOps
 
How to Avoid Pitfalls in Schema Upgrade with Percona XtraDB Cluster
How to Avoid Pitfalls in Schema Upgrade with Percona XtraDB ClusterHow to Avoid Pitfalls in Schema Upgrade with Percona XtraDB Cluster
How to Avoid Pitfalls in Schema Upgrade with Percona XtraDB Cluster
 
How to migrate from MySQL to MariaDB without tears
How to migrate from MySQL to MariaDB without tearsHow to migrate from MySQL to MariaDB without tears
How to migrate from MySQL to MariaDB without tears
 
How Safe is Asynchronous Master-Master Setup?
How Safe is Asynchronous Master-Master Setup?How Safe is Asynchronous Master-Master Setup?
How Safe is Asynchronous Master-Master Setup?
 
Современному хайлоду - современные решения: MySQL 8.0 и улучшения Percona
Современному хайлоду - современные решения: MySQL 8.0 и улучшения PerconaСовременному хайлоду - современные решения: MySQL 8.0 и улучшения Percona
Современному хайлоду - современные решения: MySQL 8.0 и улучшения Percona
 
How to Avoid Pitfalls in Schema Upgrade with Galera
How to Avoid Pitfalls in Schema Upgrade with GaleraHow to Avoid Pitfalls in Schema Upgrade with Galera
How to Avoid Pitfalls in Schema Upgrade with Galera
 
How Safe is Asynchronous Master-Master Setup?
 How Safe is Asynchronous Master-Master Setup? How Safe is Asynchronous Master-Master Setup?
How Safe is Asynchronous Master-Master Setup?
 
Introduction to MySQL Query Tuning for Dev[Op]s
Introduction to MySQL Query Tuning for Dev[Op]sIntroduction to MySQL Query Tuning for Dev[Op]s
Introduction to MySQL Query Tuning for Dev[Op]s
 
Billion Goods in Few Categories: How Histograms Save a Life?
Billion Goods in Few Categories: How Histograms Save a Life?Billion Goods in Few Categories: How Histograms Save a Life?
Billion Goods in Few Categories: How Histograms Save a Life?
 
A Billion Goods in a Few Categories: When Optimizer Histograms Help and When ...
A Billion Goods in a Few Categories: When Optimizer Histograms Help and When ...A Billion Goods in a Few Categories: When Optimizer Histograms Help and When ...
A Billion Goods in a Few Categories: When Optimizer Histograms Help and When ...
 
Что нужно знать о трёх топовых фичах MySQL
Что нужно знать  о трёх топовых фичах  MySQLЧто нужно знать  о трёх топовых фичах  MySQL
Что нужно знать о трёх топовых фичах MySQL
 
Billion Goods in Few Categories: How Histograms Save a Life?
Billion Goods in Few Categories: How Histograms Save a Life?Billion Goods in Few Categories: How Histograms Save a Life?
Billion Goods in Few Categories: How Histograms Save a Life?
 
MySQL Performance Schema in Action
MySQL Performance Schema in ActionMySQL Performance Schema in Action
MySQL Performance Schema in Action
 

Último

%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
masabamasaba
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
masabamasaba
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
masabamasaba
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
shinachiaurasa2
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
masabamasaba
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
masabamasaba
 

Último (20)

Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 

MySQL Cookbook: Recipes for Your Business

  • 1. MySQL Cookbook Recipes for Your Business Sveta Smirnova Principal Support Engineering Coordinator
  • 2. l Sveta Smirnova • MySQL Support Engineer • Author MySQL Troubleshooting MySQL Cookbook, 4th Edition • JSON UDF functions • FILTER clause for MySQL • Speaker • Percona Live, OOW, Fosdem, DevConf, HighLoad...
  • 3. Sveta the Speaker • Audience: DBAs • They do not write queries • They tune • Server options • Indexes • Table structure 3
  • 4. MySQL Cookbook by O’Reilly • For developers • New topic for me → challenging • In past I worked as a developer 4
  • 5. MySQL Cookbook by O’Reilly • For developers • New topic for me → challenging • In past I worked as a developer • I accepted 5
  • 6. 15 years ago • Queries sql = "SELECT name, lastname " + "FROM my_table " + "WHERE id = " + my_id 6
  • 7. 15 years ago • Placeholders sql = "SELECT name, lastname " + "FROM my_table " + "WHERE id = ?" 7
  • 8. 15 years ago • ORM Speaker(name="Sveta", lastname="Smirnova").save() 8
  • 10. Was anything changed? • Nothing • New MySQL APIs • Document Store support in MySQL • Object-oriented query language in MySQL X DevAPI 10
  • 12. MySQL CLI mysql > SELECT ’Hello, world!’; +---------------+ | Hello, world! | +---------------+ | Hello, world! | +---------------+ 1 row in set (0,00 sec) 12
  • 13. MySQL CLI • Your SQL code debugger • Tested by • Millions of users • MySQL developers • Hundreds of tests at every release • Model API for your query 13
  • 14. MySQL Shell MySQL JS > print("Hello, world!") Hello, world! MySQL JS > py Switching to Python mode... MySQL Py > print("Hello, world!") Hello, world! MySQL Py > sql Switching to SQL mode... Commands end with ; MySQL SQL > SELECT ’Hello, world!’; +---------------+ | Hello, world! | +---------------+ | Hello, world! | +---------------+ 1 row in set (0.0003 sec) 14
  • 15. MySQL Shell • New command-line client with X DevAPI support • SQL and Object-Oriented queries • MySQL Server administration • Utilities • Replication • InnoDB Cluster • Your own applications 15
  • 16. X DevAPI • Asynchronous code execution • Works with MySQL • As usual: by executing SQL • Querying tables as documents • Collections and documents support Data storage in JSON NoSQL-syntax, similar to MongoDB’s 16
  • 17. Reading Standard SQL SQL > SELECT thing, SUM(legs+arms) AS limbs -> FROM limbs GROUP BY thing -> HAVING limbs > 5; +-----------+-------+ | thing | limbs | +-----------+-------+ | armchair | 6 | | centipede | 99 | | insect | 6 | | squid | 10 | +-----------+-------+ 4 rows in set (0.0004 sec) 17
  • 18. Reading X DevAPI for tables JS > session.getCurrentSchema(). -> getTable(’limbs’). -> select().groupBy(’thing’). -> having(’SUM(legs + arms) > 5’) -> +-----------+------+------+ | thing | legs | arms | +-----------+------+------+ | armchair | 4 | 2 | | centipede | 99 | 0 | | insect | 6 | 0 | | squid | 0 | 10 | +-----------+------+------+ 4 rows in set (0.0005 sec) 18
  • 19. Reading Document Store Py > session.get_current_schema(). get_collection(’collectionLimbs’). find(’IFNULL(arms, 0) + IFNULL(legs, 0) > 5’) {"_id":"000061ed7c240000000000000002", "arms":0,"legs":6,"thing":"insect"} {"_id":"000061ed7c240000000000000003", "arms":10,"legs":0,"thing":"squid"} {"_id":"000061ed7c240000000000000005", "arms":0,"legs":99,"thing":"centipede"} {"_id":"000061ed7c240000000000000007", "arms":2,"legs":4,"thing":"armchair"} 4 documents in set (0.0004 sec) 19
  • 20. Reading Tables and Document Store JS > session.getCurrentSchema(). -> getCollectionAsTable(’collectionLimbs’). -> select(’JSON_EXTRACT(doc, "$.thing") AS thing’, -> ’SUM(IFNULL(JSON_EXTRACT(doc, "$.arms"), 0) + -> IFNULL(JSON_EXTRACT(doc, "$.legs"), 0)) AS limbs’). -> groupBy(’thing’).having(’limbs > 5’) -> +-------------+-------+ | thing | limbs | +-------------+-------+ | "insect" | 6 | | "squid" | 10 | | "centipede" | 99 | | "armchair" | 6 | +-------------+-------+ 4 rows in set (0.0006 sec) 20
  • 21. Working with Results SQL code in Python cursor = conn.cursor() cursor.execute("SELECT id, name, cats FROM profile") while True: row = cursor.fetchone() if row is None: break print(f"id: row[0], name: row[1], cats: row[2]") 21
  • 22. Working with Results X DevAPI for tables result = session.get_schema(’cookbook’). get_table(’profile’). select(’id’, ’name’, ’cats’).execute() while True: row = result.fetch_one() if row is None: break print(f"id: row[0], name: row[1], cats: row[2]") 22
  • 23. Working with Results Document Store result = session.get_schema(’cookbook’). get_collection(’collectionProfile’). find().execute() while True: doc = result.fetch_one() if doc is None: break print(f"id: doc[’id’], name: doc[’name’], cats: doc[’cats’]") 23
  • 24. Working with Results Tables and Document Store result = session.get_schema(’cookbook’). get_collection_as_table(’collectionProfile’). select(’JSON_EXTRACT(doc, "$.id") AS id’). select(’JSON_EXTRACT(doc, "$.name") AS name’). select(’JSON_EXTRACT(doc, "$.cats") AS cats’).execute() while True: row = result.fetch_one() if row is None: break print(f"id: row[0], name: row[1], cats: row[2]") 24
  • 25. Changing Data Standard SQL INSERT INTO limbs(thing, legs, arms) VALUES(’cat’, 2, 2); 25
  • 26. Changing Data X DevAPI for tables JS > session.getSchema(’cookbook’). -> getTable(’limbs’). -> update(). -> set(’legs’, 4). -> set(’arms’, 0). -> where(’thing = "cat"’) -> 26
  • 27. Changing Data Document Store Py > session.get_schema(’cookbook’). get_collection(’collectionLimbs’). add_or_replace_one(’00006002f065000000000000006b’, {"thing": "cat", "legs": 4, "arms": 0}) 27
  • 28. Changing Data Tables and Document Store JS > session.getSchema(’cookbook’). -> getCollectionAsTable(’collectionLimbs’). -> delete(). -> where(’JSON_EXTRACT(doc, "$.thing") = "cat"’) -> 28
  • 29. Character Encoding Standard API: establishing connection conn_params = { "database": "test", "host": "localhost", "user": "sveta", "password": "", "charset": "cp1251" } conn = mysql.connector.connect(**conn_params) 29
  • 30. Character Encoding Standard API: SET NAMES cursor.execute("SET NAMES utf8mb4") 30
  • 31. Character Encoding • X DevAPI • Only utf8mb4 May not work with your connector! 31
  • 32. Generating Summaries • When was the longest trip per driver? +--------+-------+------------+-------+ | rec_id | name | trav_date | miles | +--------+-------+------------+-------+ | 1 | Ben | 2014-07-30 | 152 | | 2 | Suzi | 2014-07-29 | 391 | | 3 | Henry | 2014-07-29 | 300 | | 4 | Henry | 2014-07-27 | 96 | | 5 | Ben | 2014-07-29 | 131 | | 6 | Henry | 2014-07-26 | 115 | | 7 | Suzi | 2014-08-02 | 502 | | 8 | Henry | 2014-08-01 | 197 | | 9 | Ben | 2014-08-02 | 79 | | 10 | Henry | 2014-07-30 | 203 | +--------+-------+------------+-------+ 32
  • 33. Generating Summaries Naive solution mysql> SELECT name, trav_date, MAX(miles) AS ’longest trip’ -> FROM driver_log GROUP BY name; ERROR 1055 (42000): ’cookbook.driver_log.trav_date’ isn’t in GROUP BY mysql> SET sql_mode=”; Query OK, 0 rows affected (0,00 sec) mysq> SELECT name, trav_date, MAX(miles) AS ’longest trip’ -> FROM driver_log GROUP BY name; +-------+------------+--------------+ | name | trav_date | longest trip | +-------+------------+--------------+ | Ben | 2014-07-30 | 152 | | Suzi | 2014-07-29 | 502 | | Henry | 2014-07-29 | 300 | +-------+------------+--------------+ 3 rows in set (0,00 sec) 33
  • 34. Generating Summaries Legacy solution mysql> CREATE TEMPORARY TABLE t -> SELECT name, MAX(miles) AS miles -> FROM driver_log GROUP BY name; mysql> SELECT d.name, d.trav_date, d.miles AS ’longest trip’ -> FROM driver_log AS d INNER JOIN t USING (name, miles) -> ORDER BY name; +-------+------------+--------------+ | name | trav_date | longest trip | +-------+------------+--------------+ | Ben | 2014-07-30 | 152 | | Henry | 2014-07-29 | 300 | | Suzi | 2014-08-02 | 502 | +-------+------------+--------------+ mysql> DROP TABLE t; 34
  • 35. Generating Summaries Common Table Expression (CTE) mysql> WITH t AS -> (SELECT name, MAX(miles) AS miles -> FROM driver_log GROUP BY name) -> SELECT d.name, d.trav_date, d.miles AS ’longest trip’ -> FROM driver_log AS d INNER JOIN t USING (name, miles) -> ORDER BY name; +-------+------------+--------------+ | name | trav_date | longest trip | +-------+------------+--------------+ | Ben | 2014-07-30 | 152 | | Henry | 2014-07-29 | 300 | | Suzi | 2014-08-02 | 502 | +-------+------------+--------------+ 3 rows in set (0.01 sec) 35
  • 36. Storing Errors with Diagnostic Area Foreign keys ALTER TABLE movies_actors_link ADD FOREIGN KEY(movie_id) REFERENCES movies(id); ALTER TABLE movies_actors_link ADD FOREIGN KEY(actor_id) REFERENCES actors(id); 36
  • 37. Storing Errors with Diagnostic Area Custom error log CREATE TABLE ‘movies_actors_log‘ ( ‘err_ts‘ timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, ‘err_number‘ int DEFAULT NULL, ‘err_sqlstate‘ char(5) DEFAULT NULL, ‘err_message‘ TEXT DEFAULT NULL, ‘movie_id‘ int unsigned DEFAULT NULL, ‘actor_id‘ int unsigned DEFAULT NULL ); 37
  • 38. Storing Errors with Diagnostic Area Data modification procedure CREATE PROCEDURE insert_movies_actors_link(movie INT, actor INT) BEGIN DECLARE e_number INT; DECLARE e_sqlstate CHAR(5); DECLARE e_message TEXT; DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN GET DIAGNOSTICS CONDITION 1 e_number = MYSQL_ERRNO, e_sqlstate = RETURNED_SQLSTATE, e_message = MESSAGE_TEXT; INSERT INTO movies_actors_log(err_number, err_sqlstate, err_message, movie_id, actor_id) VALUES(e_number, e_sqlstate, e_message, movie, actor); RESIGNAL; END; INSERT INTO movies_actors_link VALUES(movie, actor); END 38
  • 39. Storing Errors with Diagnostic Area After few errors mysql> SELECT err_ts, err_message, movie_id, actor_id -> FROM movies_actors_logG *************************** 1. row *************************** err_ts: 2022-02-28 04:23:28 err_message: Cannot add or update a child row: a foreign key constraint fails (‘cookbook‘.‘movies_actors_link‘, CONSTRAINT ‘movies_actors_link_ibfk_1‘ FOREIGN KEY (‘movie_id‘) REFERENCES ‘movies‘ (‘id‘)) movie_id: 7 actor_id: 11 ... 39
  • 40. Storing Errors with Diagnostic Area After few errors *************************** 2. row *************************** err_ts: 2022-02-28 04:23:38 err_message: Column ’movie_id’ cannot be null movie_id: NULL actor_id: 10 *************************** 3. row *************************** err_ts: 2022-02-28 04:23:48 err_message: Duplicate entry ’6-9’ for key ’movies_actors_link.movie_id’ movie_id: 6 actor_id: 9 40
  • 41. Export and Import • Industry standard mysqldump MyDumper XtraBackup 41
  • 42. Export and Import • mysqlpump: mysqldump on steroids • Legacy commands removed ALTER TABLE ... DISABLE KEYS • Multithreaded --default-parallelism • More filters --exclude-* --include-* --skip-definer 42
  • 43. Export and Import • MySQL Shell Utilities Export into CSV JS > util.exportTable( -> ’limbs’, ’BACKUP/cookbook/limbs.csv’, -> dialect: "csv-unix") Import from CSV Py > sql CREATE TABLE test.limbs LIKE limbs; Fetching table and column names from ‘cookbook‘ for auto-completion... Press ^C to stop. Query OK, 0 rows affected (0.0264 sec) Py > util.import_table("BACKUP/cookbook/limbs.csv", "dialect": "csv-unix", "schema": "test") 43
  • 44. Export and Import • MySQL Shell Utilities • Import from JSON $ mysqlsh cbuser:cbpass@127.0.0.1:33060/cookbook > --import limbs.json CollectionLimbs WARNING: Using a password on the command line interface can be insecure. Importing from file "limbs.json" to collection ‘cookbook‘.‘CollectionLimbs‘ in MySQL Server at 127.0.0.1:33060 .. 11.. 11 Processed 506 bytes in 11 documents in 0.0067 sec (11.00 documents/s) Total successfully imported documents 11 (11.00 documents/s) 44
  • 45. Export and Import • MySQL Shell Utilities Import from mongoexport JS > options = { -> "schema": "cookbook", -> "collection": "blogs", -> "convertBsonTypes": true -> } -> JS > util.importJson("blogs.json", options) Importing from file "blogs.json" to collection ‘cookbook‘.‘blogs‘ in MySQL Server at 127.0.0.1:33060 .. 2.. 2 Processed 240 bytes in 2 documents in 0.0070 sec (2.00 documents/s) Total successfully imported documents 2 (2.00 documents/s) 45
  • 46. Export and Import • MySQL Shell Utilities • Export into JSON $ mysqlsh cbuser:cbpass@127.0.0.1:33060/cookbook > -e "limbs=shell.getSession().getSchema(’cookbook’). > getCollection(’collectionLimbs’). > find().execute().fetchAll(); > println(limbs);" > limbs.json 46
  • 47. Metadata Column metadata def get_enumorset_info(client, db_name, tbl_name, col_name) sth = client.prepare( "SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? AND COLUMN_NAME = ?") res = sth.execute(db_name, tbl_name, col_name) return nil if res.count == 0 # no such column row = res.first info = {} info["name"] = row.values[0] return nil unless row.values[1] =~ /^(ENUM|SET)((.*))$/i info["type"] = $1 info["values"] = $2.split(",").collect |val| val.sub(/^’(.*)’$/, "1") info["nullable"] = (row.values[2].upcase == "YES") info["default"] = row.values[3] return info end 47
  • 48. Metadata Checking in the application info = get_enumorset_info(conn, db_name, tbl_name, col_name) if info is not None and info[’type’].upper() == ’ENUM’: valid = 1 if list(map(lambda v: v.upper(), info[’values’])).count(val.upper()) > 0 else 0 48
  • 49. Metadata All tables, referenced by foreign keys mysql> SELECT ku.TABLE_NAME AS child, -> ku.REFERENCED_TABLE_NAME AS parent -> FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc -> JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ku -> USING (CONSTRAINT_NAME, TABLE_SCHEMA, TABLE_NAME) -> WHERE CONSTRAINT_TYPE=’FOREIGN KEY’ AND -> ku.TABLE_SCHEMA=’cookbook’; +--------------------+--------+ | child | parent | +--------------------+--------+ | movies_actors_link | movies | | movies_actors_link | actors | +--------------------+--------+ 2 rows in set (0,00 sec) 49
  • 50. Metadata Result: standard API cursor = conn.cursor(buffered=True) cursor.execute(stmt) # metadata information becomes available at this point ... print("Number of rows: %d" % cursor.rowcount) if cursor.with_rows: ncols = len(cursor.description) else: ncols = 0 # no result set print("Number of columns: %d" % ncols) if ncols == 0: print("Note: statement has no result set") else: for i, col_info in enumerate(cursor.description): name, type, _, _, _, _, nullable, flags, *_ = col_info print("--- Column %d (%s) ---" % (i, name)) ... 50
  • 51. Metadata • Result: X DevAPI • Only basic information "executionTime": "0.0007 sec", "affectedRowCount": 0, "affectedItemsCount": 0, "warningCount": 0, "warningsCount": 0, "warnings": [], "info": "", "autoIncrementValue": 0 51
  • 52. Validation and Formatting CHECK Constraints mysql> ALTER TABLE patients ADD CONSTRAINT date_check -> CHECK((date_departed IS NULL) OR -> (date_departed >= date_arrived)); mysql> INSERT INTO patients (national_id, name, surname, -> gender, age, diagnosis, date_arrived, date_departed) -> VALUES(’34GD429520’, ’John’, ’Doe’, ’M’, 45, -> ’Data Phobia’, ’2020-07-20’, ’2020-05-31’); ERROR 3819 (HY000): Check constraint ’date_check’ is violated. 52
  • 53. Validation and Formatting JSON Schema for collections JS > schema={ -> "$schema": "http://json-schema.org/draft-07/schema", -> "id": "http://example.com/cookbook.json", -> "type": "object", -> "description": "Table limbs as a collection", -> "properties": { -> "thing": {"type": "string"}, -> "legs": { -> "anyOf": [{"type": "number"},{"type": "null"}], -> "default": 0 -> }, -> "arms": { -> "anyOf": [{"type": "number"},{"type": "null"}], -> "default": 0 -> }}, -> "required": ["thing","legs","arms"] } 53
  • 54. Validation and Formatting JS > collectionLimbs=session.getCurrentSchema(). -> createCollection(’collectionLimbs’, -> {"validation": {"level": "strict", "schema": schema}}) -> 54
  • 55. Sequences Enumerating result mysql> SELECT -> ROW_NUMBER() OVER win AS turn, -> first_name, last_name FROM name -> WINDOW win -> AS (ORDER BY RAND()); +------+------------+-----------+ | turn | first_name | last_name | +------+------------+-----------+ | 1 | Devon | White | | 2 | Kevin | Brown | | 3 | Rondell | White | | 4 | Vida | Blue | | 5 | Pete | Gray | +------+------------+-----------+ 5 rows in set (0.00 sec) 55
  • 56. Sequences Several sequences in one query mysql> WITH RECURSIVE sequences(id, geo, random) AS -> (SELECT 1, 3, FLOOR(1+RAND()*5) -> UNION ALL -> SELECT id + 1, geo * 4, FLOOR(1+RAND()*5) FROM sequences WHERE id < 5) -> SELECT * FROM sequences; +------+------+--------+ | id | geo | random | +------+------+--------+ | 1 | 3 | 4 | | 2 | 12 | 4 | | 3 | 48 | 2 | | 4 | 192 | 2 | | 5 | 768 | 3 | +------+------+--------+ 5 rows in set (0.00 sec) 56
  • 57. Joins and Subqueries How many drivers on the road? mysql> SELECT trav_date, COUNT(trav_date) AS drivers -> FROM driver_log GROUP BY trav_date ORDER BY trav_date; +------------+---------+ | trav_date | drivers | +------------+---------+ | 2014-07-26 | 1 | | 2014-07-27 | 1 | | 2014-07-29 | 3 | | 2014-07-30 | 2 | | 2014-08-01 | 1 | | 2014-08-02 | 2 | +------------+---------+ 57
  • 58. Joins and Subqueries Missed dates mysql> CREATE TABLE dates (d DATE); -> INSERT INTO dates (d) -> VALUES(’2014-07-26’),(’2014-07-27’),(’2014-07-28’), -> (’2014-07-29’),(’2014-07-30’),(’2014-07-31’), -> (’2014-08-01’),(’2014-08-02’); 58
  • 59. Joins and Subqueries When drivers have rest? mysql> SELECT dates.d -> FROM dates LEFT JOIN driver_log -> ON dates.d = driver_log.trav_date -> WHERE driver_log.trav_date IS NULL; +------------+ | d | +------------+ | 2014-07-28 | | 2014-07-31 | +------------+ 59
  • 60. Joins and Subqueries CTE: in one query WITH RECURSIVE dates (d) AS ( SELECT ’2014-07-26’ UNION ALL SELECT d + INTERVAL 1 day FROM dates WHERE d < ’2014-08-02’) SELECT dates.d, COUNT(driver_log.trav_date) AS drivers FROM dates LEFT JOIN driver_log ON dates.d = driver_log.trav_date GROUP BY d ORDER BY d; 60
  • 61. Statistics Ranking: legacy way mysql> SET @rownum := 0; Query OK, 0 rows affected (0,00 sec) mysql> SELECT @rownum := @rownum + 1 AS ‘rank‘, score FROM ranks ORDER BY score DESC; +------+-------+ | rank | score | +------+-------+ | 1 | 5 | | 2 | 4 | | 3 | 4 | | 4 | 3 | | 5 | 2 | | 6 | 2 | | 7 | 2 | | 8 | 1 | +------+-------+ 8 rows in set, 1 warning (0,00 sec) 61
  • 62. Statistics The issue! mysql> SHOW WARNINGSG *************************** 1. row *************************** Level: Warning Code: 1287 Message: Setting user variables within expressions is deprecated and will be removed in a future release. Consider alternatives: ’SET variable=expression, ...’, or ’SELECT expression(s) INTO variables(s)’. 1 row in set (0,00 sec) 62
  • 63. Statistics Ranking: Window Functions mysql> SELECT ROW_NUMBER() OVER win AS ’rank’, score -> FROM ranks WINDOW win AS (ORDER BY score DESC); +------+-------+ | rank | score | +------+-------+ | 1 | 5 | | 2 | 4 | | 3 | 4 | | 4 | 3 | | 5 | 2 | | 6 | 2 | | 7 | 2 | | 8 | 1 | +------+-------+ 8 rows in set (0,00 sec) 63
  • 64. Statistics Repeating results mysql> SELECT ROW_NUMBER() OVER win AS ’row’, -> RANK() OVER win AS ’rank’, -> score FROM ranks WINDOW win AS (ORDER BY score DESC); +------+------+-------+ | row | rank | score | +------+------+-------+ | 1 | 1 | 5 | | 2 | 2 | 4 | | 3 | 2 | 4 | | 4 | 4 | 3 | | 5 | 5 | 2 | | 6 | 5 | 2 | | 7 | 5 | 2 | | 8 | 8 | 1 | +------+------+-------+ 64
  • 65. Duplicates Duplicate users mysql> WITH tmp AS ( -> SELECT COUNT(*) AS count, last_name, first_name -> FROM catalog_list GROUP BY last_name, first_name HAVING count > 1) -> SELECT catalog_list.* -> FROM tmp INNER JOIN catalog_list USING (last_name, first_name) -> ORDER BY last_name, first_name; +-----------+------------+----------------------+ | last_name | first_name | street | +-----------+------------+----------------------+ | Baxter | Wallace | 57 3rd Ave. | | BAXTER | WALLACE | 57 3rd Ave. | | Baxter | Wallace | 57 3rd Ave., Apt 102 | | Pinter | Marlene | 9 Sunset Trail | | Pinter | Marlene | 9 Sunset Trail | +-----------+------------+----------------------+ 5 rows in set (0,00 sec) 65
  • 66. JSON • Data type JSON • Compact storage • In-place update On the source and replica binlog_row_value_options=PARTIAL_JSON • Operators -> and ->> • Functions Search, pattern support Update Validation, including JSON schema Conversion Documents join 66
  • 67. JSON • JSON Path for queries Names of book authors mysql> SELECT JSON_EXTRACT(author, ’$.name’) AS author -> FROM book_authors; +---------+ | author | +---------+ | "Paul" | | "Alkin" | | "Sveta" | +---------+ 3 rows in set (0,00 sec) 67
  • 68. JSON • JSON Path for queries Names of book authors mysql> SELECT author->’$.name’ AS author -> FROM book_authors; +---------+ | author | +---------+ | "Paul" | | "Alkin" | | "Sveta" | +---------+ 3 rows in set (0,00 sec) 68
  • 69. JSON • JSON Path for queries Removing quotes mysql> SELECT JSON_UNQUOTE( -> JSON_EXTRACT(author, ’$.name’) -> ) AS author FROM book_authors; +--------+ | author | +--------+ | Paul | | Alkin | | Sveta | +--------+ 3 rows in set (0,00 sec) 69
  • 70. JSON • JSON Path for queries Removing quotes mysql> SELECT author-»’$.name’ AS author -> FROM book_authors; +--------+ | author | +--------+ | Paul | | Alkin | | Sveta | +--------+ 3 rows in set (0,00 sec) 70
  • 71. JSON • JSON Path for queries First and last books mysql> SELECT CONCAT(author-»’$.name’, ’ ’, author-»’$.lastname’) AS author, -> author-»’$.books[0]’ AS ‘First Book‘, author-»’$.books[last]’ AS ‘Last Book‘ -> FROM book_authorsG ************************ 1. row ************************ author: Paul DuBois First Book: Software Portability with imake: ... Last Book: MySQL (Developer’s Library) ************************ 2. row ************************ author: Alkin Tezuysal First Book: MySQL Cookbook Last Book: MySQL Cookbook ************************ 3. row ************************ author: Sveta Smirnova First Book: MySQL Troubleshooting Last Book: MySQL Cookbook 71
  • 72. JSON Indexes mysql> ALTER TABLE book_authors -> ADD COLUMN lastname VARCHAR(255) -> GENERATED ALWAYS AS -> (JSON_UNQUOTE(JSON_EXTRACT(author, ’$.lastname’))); mysql> ALTER TABLE book_authors -> ADD COLUMN name VARCHAR(255) -> GENERATED ALWAYS AS (author-»’$.name’); mysql> CREATE INDEX author_name -> ON book_authors(lastname, name); 72
  • 73. Transactions Standard API conn.start_transaction() cursor = conn.cursor() # move some money from one person to the other cursor.execute("UPDATE money SET amt = amt - 6 WHERE name = ’Eve’") cursor.execute("UPDATE money SET amt = amt + 6 WHERE name = ’Ida’") cursor.close() conn.commit() 73
  • 74. Transactions X DevAPI for tables session.get_schema(’cookbook’).get_table(’money’) session.start_transaction() money.update().set(’amt’, 4).where("name = ’Eve’").execute() money.update().set(’amt’, 10).where("name = ’Ida’").execute() session.commit() 74
  • 75. Transactions Document Store money = session.get_schema(’cookbook’).get_collection(’collectionMoney’) session.start_transaction() Eve = money.find("name = ’Eve’").execute().fetch_one() Ida = money.find("name = ’Ida’").execute().fetch_one() Eve.amt = Eve.amt - 6 Ida.amt = Ida.amt + 6 money.replace_one(Eve._id, Eve) money.replace_one(Ida._id, Ida) session.commit() 75
  • 76. More Information X DevAPI X Protocol MySQL Shell Common Table Expressions Window functions JSON functions 76