Sick and tired of "X technology is only good for starting out; after you do, move to Y"? Good news - you don’t need to move away, you just need to get in further! In this talk, you'll learn about improvements in the newest version of the most used database in the world. What are Window Functions? How do you use CTEs? How can the new default encoding help me and what should I look for when upgrading versions?
3. @gabidavila
Brief History ● Created to handle from up
to 10 to 100M rows or
around 100MB/table
● Now supports terabyte-
sized databases
● Supports SQL standards as
new as SQL 2016
● But... some stuff from SQL
2003 just became available
(Window Functions, CTEs)
● What is awesome now?
23 OF MAY
1995
GPL V2
11. @gabidavila
User Management
● Reusable Permissions/Roles
● Password policy
● New Password
● Reuse of Password
● Expiration
● Rotation
gabi.fyi/roles-mysql
12. @gabidavila
User Management
● GRANT doesn’t create users anymore, it just… grants!!!
● No more FLUSH PRIVILEGES
● No more googling all the time how to create users with the right
permissions!
gabi.fyi/roles-mysql
13. @gabidavila
Creating a READONLY role
CREATE ROLE 'readonly';
GRANT SELECT ON app.* TO 'readonly';
● Create the Role
● Define the Privileges
gabi.fyi/roles-mysql
14. @gabidavila
Creating a user with READONLY role
● Create the User
● Grant the Role
CREATE USER 'gabriela'@'%' IDENTIFIED BY 'my_pwd';
GRANT 'readonly' TO 'gabriela'@'%';
gabi.fyi/roles-mysql
17. @gabidavila
New default Collation
● utf8mb4_0900_ai_ci
● UTF-8 version 9.0 support
● Accent Insensitive
● Case Insensitive
● No more 🍣 = 🍺 bug
● Caused by utf8mb4_general_ci or utf8mb4_unicode_ci
More information on how collations behave here.
18. @gabidavila
Other defaults & variables
● Binary log (log_bin) is enabled by default
● SHA-2 for authentication
● Mandatory default value for TIMESTAMP
● New variable to dedicated servers (default OFF),
innodb_dedicated_server=ON , controls dynamically:
● innodb_buffer_pool_size
● innodb_log_file_size
● innodb_flush_method
21. @gabidavila
Descending Indexes
Up to 5.7
● Syntax allowed ASC or DESC when defining an index
However...
An index_col_name specification can end with ASC or DESC. These keywords are
permitted for future extensions for specifying ascending or descending index value
storage. Currently, they are parsed but ignored; index values are always stored in
ascending order.
23. @gabidavila
Descending Indexes
● No longer ignored and forcibly created as ASC
● Actually works!!!
ALTER TABLE users
ADD INDEX ix_username (username DESC);
24. @gabidavila
Descending Indexes
Can be scanned as intended or backwards
SELECT *
FROM users
WHERE username LIKE 'g%'
ORDER BY username DESC;
-- OR WITH THE SAME COST
SELECT *
FROM users
WHERE username LIKE 'g%'
ORDER BY username;
26. @gabidavila
DESCRIBE `users`;
Type Null Key Default Extra
`id`
bigint(20)
unsigned
NO PRI auto_increment
`username` varchar(255) NO
`created_at` timestamp NO CURRENT_TIMESTAMP DEFAULT_GENERATED
`updated_at` timestamp NO CURRENT_TIMESTAMP
DEFAULT_GENERATED on
update CURRENT_TIMESTAMP
27. @gabidavila
Invisible Indexes
● Not used by the optimizer
● Visible by default, to create an invisible index:
ALTER TABLE users
ADD INDEX ix_username (username) INVISIBLE;
ALTER TABLE users ALTER INDEX ix_username INVISIBLE;
ALTER TABLE users ALTER INDEX ix_username VISIBLE;
● Toggle visibility:
31. @gabidavila
Instant
● Add columns without doing a INPLACE/COPY operation
● Must be appending a column to a table
● Must not have a DEFAULT on the new column
● Rename Table
● Modify Columns
● Virtual Columns
● SET/DROP DEFAULT value of a column
32. @gabidavila
Example
mysql> ALTER TABLE orders ADD COLUMN total DECIMAL(10,2) NOT NULL,
ALGORITHM=INSTANT;
Query OK, 0 rows affected (0.26 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> SELECT count(*) FROM orders;
+----------+
| COUNT(*) |
+----------+
| 50996708 |
+----------+
1 row in set (7.80 sec)
35. @gabidavila
What they do?
● Allows to analyze the rows of a given result set
● Can behave like a GROUP BY without changing the result set
● Allows you to use a frame to "peek" OVER a PARTITION of a window
40. @gabidavila
Previous and Next orders | LAG and LEAD
SELECT id,
user_id,
status,
LAG(created_at) OVER(ORDER BY created_at) AS previous_order,
created_at,
LEAD(created_at) OVER(ORDER BY created_at) AS next_order
FROM orders
WHERE user_id = 654321
ORDER BY created_at
LIMIT 10;
47. @gabidavila
Common Table Expressions
● Similar to CREATE [TEMPORARY] TABLE
● Doesn’t need CREATE privilege
● Can reference other CTEs (if those are already defined)
● Can be recursive
● Easier to read
48. @gabidavila
Recursive CTE
● Useful with hierarchical data
● The Recipe is:
● Base query comes first
● Second query comes after an UNION statement
● And the stop condition should be on the recursive call
51. @gabidavila
Recursive CTE
WITH RECURSIVE tree (depth_level, node, path, node_id) AS (
SELECT 1,
CAST('root' AS CHAR(255)),
CAST('root' AS CHAR(65535)),
0
)
SELECT * FROM tree;
52. @gabidavila
Recursive CTE
WITH RECURSIVE tree (depth_level, node, path, node_id) AS (
SELECT 1,
CAST('root' AS CHAR(255)),
CAST('root' AS CHAR(65535)),
0
UNION ALL
SELECT tree.depth_level + 1,
categories.name,
CONCAT_WS('/', tree.path, categories.name),
categories.id
FROM tree
INNER JOIN categories
ON tree.node_id = categories.parent_category_id
WHERE tree.depth_level < 5
)
SELECT * FROM tree ORDER BY path;
54. @gabidavila
Who never did this? | The most expensive order for each user
SELECT users.id,
users.username,
(SELECT id FROM orders
WHERE users.id = user_id
ORDER BY total LIMIT 1) AS order_id,
(SELECT total FROM orders
WHERE users.id = user_id
ORDER BY total LIMIT 1) AS order_total
FROM users
ORDER BY users.id
LIMIT 10;