SlideShare a Scribd company logo
Query Optimization with MySQL 5.6: 
Old and New Tricks 
Jaime Crespo 
Senior MySQL Instructor 
Percona Live London 2013 
November 11, 2013
About This Presentation 
• Objective #1: 
- Get faster queries 
• Reminder of some well-known query 
optimization techniques 
- Focus on new 5.6 query features 
• For other performance tricks with MySQL & 
InnoDB: 
- InnoDB Architecture and Performance 
Optimization with Peter Zaitsev at 2pm 
2 www.percona.com
Agenda 
1. Introduction and Environment Setup 
2. Server Update and Configuration 
3. Tools for Query Profiling 
4. Indexing: Old and New Strategies 
5. New Query Planner Features 
6. Results and wrap-up 
3 www.percona.com
Example Platform 
• Sample LAMP Application 
- 'My Movies' PHP Script 
- Example movie database 
• Distributed as a VirtualBox VM 
- Import percona_live.ova 
- User: percona / pass: percona 
- Make sure httpd and PS are running 
- Optionally: startxfce4 
• Currently no design optimization, no indexes 
(except PK), no proper query design 
4 www.percona.com
Query Optimization with MySQL 5.6: Old and New Tricks 
SERVER UPDATE AND 
CONFIGURATION 
5 www.percona.com 5
Basic Configuration Review 
• InnoDB as the default engine (default in 5.5) 
• InnoDB File Per Table (default in 5.6) 
• Larger Buffer Pool and Transaction Log 
(changed in 5.6) 
• Row Based Replication and tx_isolation 
• Performance Schema overhead (enabled by 
default in 5.6) 
• InnoDB page checksum (changed in 5.6) 
• InnoDB Old Blocks time (changed in 5.6) 
6 www.percona.com
Query Optimization with MySQL 5.6: Old and New Tricks 
TOOLS FOR QUERY PROFILING 
7 www.percona.com 5
EXPLAIN 
• EXPLAIN is most important tool for the 
MySQL DBA and Developer 
• It provides: 
- The query plan strategy 
- The index(es) to be used 
- The order of table access 
- An estimation of the number of rows to be 
examined! 
8 www.percona.com 5
EXPLAIN on DML 
• EXPLAIN is now available also for 
INSERT, UPDATE and DELETE 
mysql> EXPLAIN DELETE FROM title WHERE title = 'Pilot'G! 
********************* 1. row *********************! 
id: 1! 
select_type: SIMPLE! 
table: title! 
type: range! 
possible_keys: PRIMARY,title! 
key: title! 
key_len: 77! 
ref: NULL! 
rows: 1380! 
Extra: Using where! 
1 row in set (0.00 sec)! 
9 www.percona.com 5
Structured EXPLAIN 
mysql> EXPLAIN FORMAT=JSON SELECT COUNT(*) FROM title 
WHERE (title = 'Pilot' OR production_year > 2010) 
AND kind_id < 4G 
*************************** 1. row ***************************! 
EXPLAIN: {! 
"query_block": {! 
"select_id": 1,! 
"table": {! 
"table_name": "title",! 
"access_type": "index_merge",! 
"possible_keys": [! 
"title",! 
"production_year"! 
],! 
"key": "sort_union(title,production_year)",! 
"key_length": "77,5",! 
"rows": 4434,! 
"filtered": 100,! 
"attached_condition": "(((`imdb`.`title`.`title` = 'Pilot') or 
(`imdb`.`title`.`production_year` > 2010)) and 
(`imdb`.`title`.`kind_id` < 4))"! 
}! 
}! 
}! 
10 www.percona.com 5
Optimizer Trace 
• Allows profiling of MySQL query planner 
• It shows not only information about the 
final query plan (EXPLAIN), but also about 
other discarded strategies, and its 
“execution cost” 
• It can be accessed via the 
INFORMATION_SCHEMA database 
• It is off by default 
11 www.percona.com 5
Checking the Optimizer Trace 
• mysql> SET optimizer_trace="enabled=on"; 
• mysql> SELECT COUNT(*) FROM title WHERE 
(title = 'Pilot' OR production_year > 
2010) AND kind_id < 4; 
+----------+ 
| COUNT(*) | 
+----------+ 
| 3050 | 
+----------+ 
1 row in set (0.01 sec) 
• mysql> SELECT trace FROM 
information_schema.optimizer_trace; 
12 www.percona.com 5
Checking the Optimizer Trace 
(cont.) 
{ 
"range_scan_alternatives": [ 
{ 
"index": "production_year", 
"ranges": [ 
"2010 < production_year" 
], 
"index_dives_for_eq_ranges": true, 
"rowid_ordered": false, 
"using_mrr": false, 
"index_only": true, 
"rows": 3054, 
"cost": 615.16, 
"chosen": true 
} 
], 
"index_to_merge": "production_year", 
"cumulated_cost": 905.69 
} 
], 
"cost_of_reading_ranges": 905.69, 
"cost_sort_rowid_and_read_disk": 3672.8, 
"cost_duplicate_removal": 9467.6, 
"total_cost": 14046 
} 
], 
"chosen_range_access_summary": { 
"range_access_plan": { 
"type": "index_merge", 
"index_merge_of": [ 
13 www.percona.com 5
Limitations of EXPLAIN 
• It does not really execute the query 
- Not even subqueries any more 
• The row statistics can be sometimes very 
off 
• It does not give us information about 
temporary tables (on disk or memory?), 
subtask timing, query cache hit, etc. 
14 www.percona.com 5
Handler Statistics 
• They provide time & memory status-independency: 
mysql> SHOW SESSION STATUS LIKE 'Hand%'; 
+----------------------------+-------+ 
| Variable_name | Value | 
+----------------------------+-------+ 
| Handler_commit | 1 | 
| Handler_delete | 0 | 
| Handler_discover | 0 | 
| Handler_external_lock | 2 | 
| Handler_mrr_init | 0 | 
| Handler_prepare | 0 | 
| Handler_read_first | 0 | 
| Handler_read_key | 1 | 
| Handler_read_last | 0 | 
| Handler_read_next | 266 | 
| Handler_read_prev | 0 | 
| Handler_read_rnd | 0 | 
| Handler_read_rnd_next | 0 | 
| Handler_rollback | 0 | 
| Handler_savepoint | 0 | 
| Handler_savepoint_rollback | 0 | 
| Handler_update | 0 | 
| Handler_write | 0 | 
+----------------------------+-------+ 
18 rows in set (0.00 sec) 
15 www.percona.com 5
Slow Query Log and pt-query-digest 
• Works on all MySQL versions 
- Specially useful in combination with the 
extended log statistics in Percona Server 
SET GLOBAL log_slow_verbosity = 'full'; 
! 
# Time: 130601 8:01:06.058915 
# User@Host: root[root] @ localhost [] Id: 42 
# Schema: imdb Last_errno: 0 Killed: 0 
# Query_time: 7.725616 Lock_time: 0.000328 Rows_sent: 4 Rows_examined: 1543720 
Rows_affected: 0 
# Bytes_sent: 272 Tmp_tables: 0 Tmp_disk_tables: 0 Tmp_table_sizes: 0 
# QC_Hit: No Full_scan: Yes Full_join: No Tmp_table: No Tmp_table_on_disk: No 
# Filesort: No Filesort_on_disk: No Merge_passes: 0 
SET timestamp=1370073666; 
SELECT id,title,production_year FROM title WHERE title = 'Bambi';! 
16 www.percona.com
pt-query-digest 
slow query log 
general query log 
tcpdump pt-query-digest report 
binary log 
process list 
input tool output 
17 www.percona.com
pt-query-digest Report 
# Profile! 
# Rank Query ID Response time Calls R/Call Apdx V/M Item! 
# ==== ================== =============== ===== ======= ==== ===== =======! 
# 1 0xA8D2BBDE7EBE7822 4932.2992 28.8% 78 63.2346 0.00 5.22 SELECT person_info! 
# 2 0xFE25DAF5DBB71F49 4205.2160 24.6% 130 32.3478 0.00 3.47 SELECT title! 
# 3 0x70DAC639802CA233 1299.6269 7.6% 14 92.8305 0.00 0.17 SELECT cast_info! 
# 4 0xE336B880F4FEC4B8 1184.5101 6.9% 294 4.0289 0.36 2.29 SELECT cast_info! 
# 5 0x60550B93960F1837 905.1648 5.3% 60 15.0861 0.05 1.33 SELECT name! 
# 6 0xF46D5C09B4E0CA2F 777.2446 4.5% 16340 0.0476 1.00 0.17 SELECT char_name! 
# 7 0x09FCFFF0E5BC929F 747.4346 4.4% 130 5.7495 0.53 7.69 SELECT name! 
# 8 0x9433950BE12B9470 744.1755 4.4% 14368 0.0518 1.00 0.18 SELECT name! 
# 9 0x4DC0E044996DA715 448.5637 2.6% 130 3.4505 0.65 8.31 SELECT title! 
# 10 0x09FB72D72ED18E93 361.1904 2.1% 78 4.6306 0.28 1.89 SELECT cast_info title 
#! 
# Query 1: 0.02 QPS, 1.40x concurrency, ID 0xA8D2BBDE7EBE7822 at byte 25744265! 
# Attribute pct total min max avg 95% stddev median! 
# ============ === ======= ======= ======= ======= ======= ======= =======! 
# Count 0 78! 
# Exec time 28 4932s 11s 109s 63s 88s 18s 63s! 
# Lock time 0 724ms 36us 642ms 9ms 11ms 72ms 93us! 
# Rows sent 7 12.95k 86 334 170.05 329.68 89.24 136.99! 
# Rows examine 14 168.99M 2.17M 2.17M 2.17M 2.17M 0 2.17M! 
# Rows affecte 0 0 0 0 0 0 0 0! 
# Rows read 7 12.95k 86 334 170.05 329.68 89.24 136.99! 
# Bytes sent 5 2.39M 16.18k 54.14k 31.43k 54.03k 13.47k 25.99k! 
18 www.percona.com
performance_schema 
• Integrated profiling tool 
• Not new, but improved significately for 5.6 
• Substitutes the old PROFILING interface 
• Can have a 5-10% overhead by default 
• Can be used to monitor several runtime 
statistics, among them, query execution 
statistics of the latest queries: 
SELECT * FROM 
performance_schema.events_statements_history_long! 
19 www.percona.com
Query Optimization with MySQL 5.6: Old and New Tricks 
INDEXING: OLD AND NEW 
STRATEGIES 
20 www.percona.com 5
Advantages of Indexing 
• Faster Filtering 
• Faster Column Return (Covering Index) 
• Faster Ordering 
• Certain Faster Functions (max, min) 
21 www.percona.com
Faster Filtering 
• Indexes allow to return results by reading 
a fewer number of records 
- We should minimize the rows value in 
EXPLAIN/Handlers 
- const > ref > range > index > ALL! 
• Usually, only a single index can be used 
per table access 
- Compound indexes may provide higher 
filtering rate 
22 www.percona.com
Compound Indexes 
• Column Order in Index Does Matter: 
- Order by decreasing selectivity 
- Only one range access per index* 
23 www.percona.com
Covering Index Technique 
• Additional columns can be indexed in 
order to speed-up column retrieval 
• Specially interesting in n-to-n relationship 
tables 
• Not possible if the number or size of 
columns is too large (e.g. SELECT *, 
BLOBs) 
24 www.percona.com
Index Condition Pushdown 
• Let’s prepare a use case: 
UPDATE cast_info SET note = left(note, 
250); 
ALTER TABLE cast_info MODIFY note 
varchar(250), ADD INDEX role_id_note 
(role_id, note); ! 
• We want to execute: 
SELECT * FROM cast_info 
WHERE role_id = 1 
and note like '%Jaime%‘;! 
25 www.percona.com 5
Without ICP (5.5) 
mysql> EXPLAIN SELECT * 
FROM cast_info 
WHERE role_id = 1 
and note like '%Jaime%'G 
********** 1. row ********** 
id: 1 
select_type: SIMPLE 
table: cast_info 
type: ref 
possible_keys: role_id_note 
key: role_id_note 
key_len: 4 
ref: const 
rows: 11553718 
Extra: Using where 
1 row in set (0.01 sec)! 
mysql> SHOW STATUS like 'Hand 
%';! 
+----------------------------+---------+! 
| Variable_name | Value |! 
+----------------------------+---------+! 
| Handler_commit | 1 |! 
| Handler_delete | 0 |! 
| Handler_discover | 0 |! 
| Handler_prepare | 0 |! 
| Handler_read_first | 0 |! 
| Handler_read_key | 1 |! 
| Handler_read_last | 0 |! 
| Handler_read_next | 8346769 |! 
| Handler_read_prev | 0 |! 
| Handler_read_rnd | 0 |! 
| Handler_read_rnd_next | 0 |! 
| Handler_rollback | 0 |! 
| Handler_savepoint | 0 |! 
| Handler_savepoint_rollback | 0 |! 
| Handler_update | 0 |! 
| Handler_write | 0 |! 
+----------------------------+---------+! 
16 rows in set (0.00 sec)! 
26 www.percona.com 5
With ICP (5.6) 
mysql> EXPLAIN SELECT * 
FROM cast_info 
WHERE role_id = 1 and note like 
'%Jaime%'G 
************ 1. row ************ 
id: 1 
select_type: SIMPLE 
table: cast_info 
type: ref 
possible_keys: role_id_note 
key: role_id_note 
key_len: 4 
ref: const 
rows: 10259274 
Extra: Using index 
condition 
1 row in set (0.00 sec)! 
mysql> SHOW STATUS like 'Hand%';! 
+----------------------------+-------+! 
| Variable_name | Value |! 
+----------------------------+-------+! 
| Handler_commit | 1 |! 
| Handler_delete | 0 |! 
| Handler_discover | 0 |! 
| Handler_external_lock | 2 |! 
| Handler_mrr_init | 0 |! 
| Handler_prepare | 0 |! 
| Handler_read_first | 0 |! 
| Handler_read_key | 1 |! 
| Handler_read_last | 0 |! 
| Handler_read_next | 266 |! 
| Handler_read_prev | 0 |! 
| Handler_read_rnd | 0 |! 
| Handler_read_rnd_next | 0 |! 
| Handler_rollback | 0 |! 
| Handler_savepoint | 0 |! 
| Handler_savepoint_rollback | 0 |! 
| Handler_update | 0 |! 
| Handler_write | 0 |! 
+----------------------------+-------+! 
18 rows in set (0.00 sec) 
27 www.percona.com 5
Comparison of ICP Execution 
• Execution time for this example: 
• MySQL 5.5: 5.76 sec 
• MySQL 5.6: 1.09 sec 
• Over 5x faster 
• In this example, it would not work with a 
prefix index (e.g. TEXT/BLOB), as it must 
search the whole field 
• Fun fact: if covering technique is tried, it actually runs 
slower than with ICP for this case/hardware (#68554) 
28 www.percona.com 5
ICP and Indexing 
• ICP will change the way we index our tables 
SELECT * FROM cast_info 
FORCE INDEX(person_role_id_role_id) 
WHERE person_role_id > 0 
and person_role_id < 150000 
and role_id > 1 and role_id < 7;! 
• For example, a multiple column index can be, in 
some cases, efficiently used for a range 
condition on several columns: 
• Effectiveness is highly dependent on how selective 
is the second part of the index (an “index scan” is 
still done at engine level) 
29 www.percona.com
Index for Sorts 
• Additional columns can be indexed in 
order to speed up ordering of rows 
• Only effective in simple patterns 
• GROUP BY operations are essentially 
sorts 
• They can also be greatly improved 
with the right indexes in some cases 
30 www.percona.com
Multi-Range Read (MRR) 
• Reorders access to table data when using a 
secondary index on disk for sequential I/O 
- Like ICP, its efficiency is highly dependent on 
data distribution and memory contents 
• It also depends on hardware sequential 
access (e.g., InnoDB’s read ahead) 
- May not be useful on SSDs 
• Not compatible with Using index 
• Only for range access and equi-joins 
31 www.percona.com 5
MRR Example 
• We want to execute: 
SELECT * FROM cast_info 
WHERE person_role_id > 0 
and person_role_id < 150000; 
SELECT * FROM cast_info 
WHERE role_id = 3 
and person_role_id > 0 
and person_role_id < 500000;! 
• We will use these indexes, respectively: 
ALTER TABLE cast_info 
ADD INDEX person_role_id (person_role_id); 
ALTER TABLE cast_info 
ADD INDEX person_role_id_role_id (person_role_id, 
role_id);! 
32 www.percona.com 5
Without MRR (5.5) 
mysql> SHOW STATUS like 'Hand%';! 
+----------------------------+---------+! 
| Variable_name | Value |! 
+----------------------------+---------+! 
| Handler_commit | 1 |! 
| Handler_delete | 0 |! 
| Handler_discover | 0 |! 
| Handler_prepare | 0 |! 
| Handler_read_first | 0 |! 
| Handler_read_key | 1 |! 
| Handler_read_last | 0 |! 
| Handler_read_next | 4654312 |! 
| Handler_read_prev | 0 |! 
| Handler_read_rnd | 0 |! 
| Handler_read_rnd_next | 0 |! 
| Handler_rollback | 0 |! 
| Handler_savepoint | 0 |! 
| Handler_savepoint_rollback | 0 |! 
| Handler_update | 0 |! 
| Handler_write | 0 |! 
+----------------------------+---------+! 
16 rows in set (0.00 sec) 
mysql> EXPLAIN SELECT * FROM 
cast_info FORCE 
INDEX(person_role_id) WHERE 
person_role_id > 0 and 
person_role_id < 150000G 
*********** 1. row *********** 
id: 1 
select_type: SIMPLE 
table: cast_info 
type: range 
possible_keys: person_role_id 
key: person_role_id 
key_len: 5 
ref: NULL 
rows: 8966490 
Extra: Using where 
1 row in set (0.00 sec)! 
33 www.percona.com 5
With MRR (5.6) 
mysql> SHOW STATUS like 'Hand%';! 
+----------------------------+---------+! 
| Variable_name | Value |! 
+----------------------------+---------+! 
| Handler_commit | 1 |! 
| Handler_delete | 0 |! 
| Handler_discover | 0 |! 
| Handler_external_lock | 4 |! 
| Handler_mrr_init | 0 |! 
| Handler_prepare | 0 |! 
| Handler_read_first | 0 |! 
| Handler_read_key | 4654313 |! 
| Handler_read_last | 0 |! 
| Handler_read_next | 4654312 |! 
| Handler_read_prev | 0 |! 
| Handler_read_rnd | 4654312 |! 
| Handler_read_rnd_next | 0 |! 
| Handler_rollback | 0 |! 
| Handler_savepoint | 0 |! 
| Handler_savepoint_rollback | 0 |! 
| Handler_update | 0 |! 
| Handler_write | 0 |! 
+----------------------------+---------+! 
18 rows in set (0.00 sec) 
mysql> EXPLAIN SELECT * FROM 
cast_info FORCE 
INDEX(person_role_id) WHERE 
person_role_id > 0 and 
person_role_id < 150000G 
*********** 1. row *********** 
id: 1 
select_type: SIMPLE 
table: cast_info 
type: range 
possible_keys: person_role_id 
key: person_role_id 
key_len: 5 
ref: NULL 
rows: 8966490 
Extra: Using index 
condition; Using MRR 
1 row in set (0.00 sec)! 
34 www.percona.com 5
Comparison of MRR 
Execution 
• Execution time for this example: 
• MySQL 5.5: 4654312 rows in set (1 min 4.79 sec) 
• MySQL 5.6 (w/MRR, wo/ICP): 4654312 rows in set 
(48.64 sec) 
• Consistent 33% execution improvement 
for this test case 
• Difficult to see for smaller resultsets 
• What has changed? 
• 15% more “read_ahead”s, resulting in a 40% less data reads 
• Reordering has an overhead, can be tuned with 
read_rnd_buffer_size 
35 www.percona.com 5
What’s the Point for the 
‘FORCE INDEX’? 
• For demonstration purposes (full table scan 
is better here) 
• Some features are not properly detected yet: 
SELECT * 
FROM cast_info FORCE INDEX(person_role_id_role_id) 
WHERE role_id = 3 
and person_role_id > 0 
and person_role_id < 500000; 
• Full table scan (any version): Empty set 
(8.08 sec) 
• MySQL 5.5: Empty set (1 min 16.88 sec) 
• MySQL 5.6 ICP+MRR*: Empty set (0.46 sec) 
*ICP is responsible for the dramatic change in execution time, not MRR 
36 www.percona.com
Batched Key Access (BKA) 
• It retrieves keys in batches and allows 
MRR usage for JOINs, as an alternative to 
standard Nested Loop Join execution 
• Not enabled by default 
SET optimizer_switch= 
'mrr=on,mrr_cost_based=off,batched_key_access=on';! 
37 www.percona.com
Without BKA (5.5) - EXPLAIN 
...! 
************* 2. row ************* id: 1! 
select_type: SIMPLE! 
table: cast_info! 
type: ref! 
possible_keys: person_role_id! 
key: person_role_id! 
key_len: 5! 
ref: imdb.char_name.id! 
rows: 4! 
Extra: NULL! 
2 rows in set (0.00 sec)! 
mysql> EXPLAIN 
SELECT cast_info.note, char_name.name 
FROM cast_info FORCE index(person_role_id) 
JOIN char_name 
ON cast_info.person_role_id = char_name.id 
WHERE cast_info.person_role_id > 0 and 
cast_info.person_role_id < 150000 
************ 1. row ************! 
id: 1! 
select_type: SIMPLE! 
table: char_name! 
type: range! 
possible_keys: PRIMARY! 
key: PRIMARY! 
key_len: 4! 
ref: NULL! 
rows: 313782! 
Extra: Using where! 
...! 
38 www.percona.com
Without BKA (5.5) - Handlers 
mysql> SHOW STATUS like ‘Hand%’;! 
+----------------------------+---------+ 
| Variable_name | Value | 
+----------------------------+---------+ 
| Handler_commit | 1 | 
| Handler_delete | 0 | 
| Handler_discover | 0 | 
| Handler_prepare | 0 | 
| Handler_read_first | 0 | 
| Handler_read_key | 150000 | 
| Handler_read_last | 0 | 
| Handler_read_next | 4804311 | 
| Handler_read_prev | 0 | 
| Handler_read_rnd | 0 | 
| Handler_read_rnd_next | 0 | 
| Handler_rollback | 0 | 
| Handler_savepoint | 0 | 
| Handler_savepoint_rollback | 0 | 
| Handler_update | 0 | 
| Handler_write | 0 | 
+----------------------------+---------+ 
18 rows in set (0.00 sec)! 
39 www.percona.com
With BKA (5.6) - EXPLAIN 
...! 
************ 2. row ************! 
id: 1! 
select_type: SIMPLE! 
table: cast_info! 
type: ref! 
possible_keys: person_role_id! 
key: person_role_id! 
key_len: 5! 
ref: imdb.char_name.id! 
rows: 4! 
Extra: Using join buffer 
(Batched Key Access)! 
2 rows in set (0.00 sec)! 
mysql> EXPLAIN 
SELECT cast_info.note, char_name.name 
FROM cast_info FORCE index(person_role_id) 
JOIN char_name ON cast_info.person_role_id 
= char_name.id 
WHERE cast_info.person_role_id > 0 and 
cast_info.person_role_id < 150000G! 
************ 1. row ************! 
id: 1! 
select_type: SIMPLE! 
table: char_name! 
type: range! 
possible_keys: PRIMARY! 
key: PRIMARY! 
key_len: 4! 
ref: NULL! 
rows: 313782! 
Extra: Using where 
...! 
40 www.percona.com
With BKA (5.6) - Handlers 
mysql> SHOW STATUS like ‘Hand%’; 
+----------------------------+---------+ 
| Variable_name | Value | 
+----------------------------+---------+ 
| Handler_commit | 1 | 
| Handler_delete | 0 | 
| Handler_discover | 0 | 
| Handler_external_lock | 6 | 
| Handler_mrr_init | 1 | 
| Handler_prepare | 0 | 
| Handler_read_first | 0 | 
| Handler_read_key | 4804312 | 
| Handler_read_last | 0 | 
| Handler_read_next | 4804311 | 
| Handler_read_prev | 0 | 
| Handler_read_rnd | 4654312 | 
| Handler_read_rnd_next | 0 | 
| Handler_rollback | 0 | 
| Handler_savepoint | 0 | 
| Handler_savepoint_rollback | 0 | 
| Handler_update | 0 | 
| Handler_write | 0 | 
+----------------------------+---------+ 
18 rows in set (0.00 sec)! 
41 www.percona.com
Comparison of BKA 
Execution 
• Execution time for this example: 
• MySQL 5.5: 4654312 rows in set (1 min 6.78 sec) 
• MySQL 5.6 (w/MRR, w/BKA): 4654312 rows in set 
(1 min 0.47 sec) 
• The results are consistent between 
executions, but the gain is not too big. But 
if we change the join_buffer_size… 
• MySQL 5.6 (w/MRR, w/BKA, join_buffer_size = 
50M): 4654312 rows in set (19.54 sec) 
(join_buffer_size does not affect execution time in the 5.5 version) 
42 www.percona.com 5
Better Index Merge 
• In this example, it avoids a full table scan: 
mysql> EXPLAIN SELECT COUNT(*) FROM title WHERE (title = 
'Pilot' OR production_year > 2010) AND kind_id < 4G 
************************ 1. row ************************ 
id: 1 
select_type: SIMPLE 
table: title 
type: index_merge 
possible_keys: title,production_year 
key: title,production_year 
key_len: 77,5 
ref: NULL 
rows: 4434 
Extra: Using sort_union(title,production_year); 
Using where 
1 row in set (0.00 sec) 
(almost all titles have kind_id < 4) 
• MySQL 5.5: 0.79s – MySQL 5.6: 0.01s 
43 www.percona.com 5
Extended Secondary Keys 
• Implicit primary keys inside secondary keys 
can be used for filtering (ref, range, etc), not 
only for covering index or sorting. 
• Requires use_index_extensions=on 
(default) 
ALTER TABLE title add index 
(title(25)); 
SELECT COUNT(*) FROM title 
WHERE title = 'Pilot' 
AND id BETWEEN 1000 AND 1000000; 
44 www.percona.com 5
Extended Secondary Keys 
mysql> EXPLAIN SELECT COUNT(*) FROM title WHERE 
title = 'Pilot' AND id BETWEEN 1000 AND 
1000000G 
****************** 1. row ******************* 
id: 1 
select_type: SIMPLE 
table: title 
type: range 
possible_keys: PRIMARY,title 
key: title 
key_len: 81 
ref: NULL 
rows: 531 
Extra: Using index condition; Using 
where 
1 row in set (0.00 sec) 
45 www.percona.com 5
Duplicate Key Check 
mysql> alter table title add index (production_year);! 
Query OK, 0 rows affected (10.08 sec)! 
Records: 0 Duplicates: 0 Warnings: 0! 
mysql> alter table title add index (production_year); 
Query OK, 0 rows affected, 1 warning (5.11 sec) 
Records: 0 Duplicates: 0 Warnings: 1! 
! 
mysql> show warningsG! 
************************* 1. row *************************! 
Level: Note! 
Code: 1831! 
Message: Duplicate index 'production_year_2' defined on 
the table 'imdb.title'. This is deprecated and will be 
disallowed in a future release.! 
1 row in set (0.00 sec)! 
46 www.percona.com 5
pt-duplicate-key-checker 
• It detects duplicate and redundant 
indexes 
- Including primary keys at the end of 
secondary keys on InnoDB tables 
47 www.percona.com
pt-index-usage & user_stats 
• Can detect unused indexes 
- That slow down writes 
- Can also affect reads! 
- Wasted memory 
- Query optimizer woes 
48 www.percona.com
Query Optimization with MySQL 5.6: Old and New Tricks 
NEW QUERY PLANNER FEATURES 
49 www.percona.com 5
Filesort with Short LIMIT 
• Queries that require a filesort but only the first 
records are selected can benefit from this 
optimization: 
mysql> EXPLAIN select * from movie_info 
ORDER BY info LIMIT 100G 
********************* 1. row ********************* 
id: 1 
select_type: SIMPLE 
table: movie_info 
type: ALL 
possible_keys: NULL 
key: NULL 
key_len: NULL 
ref: NULL 
rows: 6927988 
Extra: Using filesort 
1 row in set (0.00 sec) 
! 
Note: Both EXPLAIN and the STATUS Handlers show the same outcome 
50 www.percona.com 5
Filesort with Short LIMIT 
(cont.) 
• SELECT * FROM movie_info ORDER 
BY info LIMIT 100;! 
- MySQL 5.5: 20.06 sec 
- MySQL 5.6 (P_S on): 9.14 sec 
- MySQL 5.6 (P_S off): 8.51 sec 
• Over 2x faster. 
• Exact speed-up may depend on the 
original sort buffer size 
51 www.percona.com 5
Subquery Optimization 
• Late Subquery Materialization 
- Useful for FROM subqueries if further 
filtering is done 
- MySQL may also decide to create its own 
index on a temporary table on memory 
SELECT * FROM title JOIN (SELECT * FROM cast_info) 
AS subselect ON subselect.movie_id = title.id WHERE 
subselect.id = 1; 
EXPLAIN: 0.00 sec (vs >2 min in 5.5) 
EXECUTION: 1m 22 sec (vs > 4 min in 5.5) 
52 www.percona.com 5
JOINs and Subqueries 
• Better detection of IN + non-dependent 
subqueries 
- Many queries do not need to be converted 
to a JOIN anymore for a proper execution 
plan 
- MySQL decides what is the best strategy: 
Materialization, Semi-Join, etc. 
53 www.percona.com 5
That Subquery in 5.5 
mysql> EXPLAIN SELECT * FROM title WHERE kind_id IN 
(SELECT id FROM kind_type WHERE kind='video game')G 
*************************** 1. row *************************** 
id: 1 
select_type: PRIMARY 
table: title 
type: ALL 
possible_keys: NULL 
key: NULL 
key_len: NULL 
ref: NULL 
rows: 1567676 
Extra: Using where 
An index on title.kind_id 
won't fix it! 
*************************** 2. row *************************** 
id: 2 
select_type: DEPENDENT SUBQUERY 
table: kind_type 
type: const 
possible_keys: PRIMARY,kind_id 
key: kind_id 
key_len: 47 
ref: const 
rows: 1 
Extra: Using index 
2 rows in set (0.00 sec)! 
54 www.percona.com 5
That Subquery in 5.6 
mysql> EXPLAIN SELECT * FROM title WHERE kind_id IN (SELECT id FROM kind_type WHERE 
kind='video game')G 
*************************** 1. row *************************** 
id: 1 
select_type: SIMPLE 
table: kind_type 
type: const 
possible_keys: PRIMARY,kind 
key: kind 
key_len: 47 
ref: const 
rows: 1 
Extra: Using index 
*************************** 2. row *************************** 
id: 1 
select_type: SIMPLE 
table: title 
type: ALL 
possible_keys: NULL 
key: NULL 
key_len: NULL 
ref: NULL 
rows: 1477989 
Extra: Using where 
2 rows in set (0.00 sec)! 
An index on title.kind_id 
can and will be very useful! 
55 www.percona.com 5
Join Order 
• Table order algorithm has been 
optimized, which leads to better query 
plans when joining many tables 
56 www.percona.com 5
Persistent Optimizer 
Statistics 
• InnoDB index statistics are no longer 
discarded on server shutdown and 
recomputed the next time a table is 
accessed 
• Controlled by variable: 
innodb_stats_persistent = ON 
(default) 
• Remember that SHOW commands/accessing to 
I_S do not automatically regenerate statistics by 
default 
57 www.percona.com 5
READ ONLY Transactions 
• START TRANSACTION READ ONLY; 
- It avoids some overhead of R/W 
transactions (MVCC) 
- Automatically used for SELECT in 
auto_commit 
- Once started, a new transaction has to be 
started to perform a write 
58 www.percona.com 5
Explicit Partition Selection 
• Usually unnecessary, as MySQL does 
automatically partition pruning 
• Can be useful combined with some non-deterministic 
functions or in some special 
cases: 
SELECT count(*) 
FROM title PARTITION(p01, p02); 
59 www.percona.com 5
Query Optimization with MySQL 5.6: Old and New Tricks 
RESULTS AND WRAP-UP 
60 www.percona.com 5
5.6 is a Great Release 
• Many optimizer changes that can 
potentially improve query execution time 
• Some of them are transparent, some 
others require tuning and understanding 
- Some old tricks and indexing strategies 
become obsolete in 5.6 
• pt-upgrade, from Percona Toolkit, and 
Percona Playback can be great tools to 
analyze improvements and regressions 
61 www.percona.com
Where to Learn More ? 
• More query and server optimization 
techniques in our training courses ( 
http://www.percona.com/training): 
- Scaling and Optimization for MySQL 
- Operations and Troubleshooting with 
MySQL 
- Moving to MySQL 5.6 
- Analysing Queries with Percona Toolkit 
- Percona Server and Tools (NEW!) 
• Ask me for a discount (only to PLUK 
attendants)! 
62 www.percona.com
Where to Learn More ? (cont.) 
• Books: 
• High Performance MySQL, 3rd Edition 
• SQL Antipatterns 
• Free MySQL Webinars: 
• http://www.percona.com/resources/ 
mysql-webinars 
63 www.percona.com
Percona Live MySQL 
Conference and Expo 2014 
• For more information and to register: 
Visit: http://www.percona.com/live/mysql-conference-2014/
Thank You! 
Jaime Crespo 
jaime.crespo@percona.com 
65 wwwww.wpe.prceorncao.cnoam.c om

More Related Content

PDF
Need for Speed: Mysql indexing
PDF
Advanced MySQL Query and Schema Tuning
PDF
56 Query Optimization
PDF
Advanced MySQL Query Tuning
PDF
0888 learning-mysql
PDF
Optimizing Queries with Explain
ODP
PDF
Mysql query optimization
Need for Speed: Mysql indexing
Advanced MySQL Query and Schema Tuning
56 Query Optimization
Advanced MySQL Query Tuning
0888 learning-mysql
Optimizing Queries with Explain
Mysql query optimization

What's hot (19)

PDF
Introduction into MySQL Query Tuning for Dev[Op]s
PPTX
Optimizing queries MySQL
PDF
Why Use EXPLAIN FORMAT=JSON?
PDF
MySQL Query tuning 101
PDF
MySQL Index Cookbook
PDF
Optimizer Trace Walkthrough
PDF
Optimizer features in recent releases of other databases
PDF
MySQL/MariaDB query optimizer tuning tutorial from Percona Live 2013
PDF
Introduction to MySQL Query Tuning for Dev[Op]s
PDF
MySQL 8.0 EXPLAIN ANALYZE
PDF
MySQL Indexing : Improving Query Performance Using Index (Covering Index)
PDF
New features in Performance Schema 5.7 in action
PDF
Using Optimizer Hints to Improve MySQL Query Performance
PDF
Using histograms to get better performance
PDF
Introduction into MySQL Query Tuning
PDF
Optimizer overviewoow2014
PDF
Basic MySQL Troubleshooting for Oracle Database Administrators
PDF
Query Optimizer in MariaDB 10.4
PDF
Lessons for the optimizer from running the TPC-DS benchmark
Introduction into MySQL Query Tuning for Dev[Op]s
Optimizing queries MySQL
Why Use EXPLAIN FORMAT=JSON?
MySQL Query tuning 101
MySQL Index Cookbook
Optimizer Trace Walkthrough
Optimizer features in recent releases of other databases
MySQL/MariaDB query optimizer tuning tutorial from Percona Live 2013
Introduction to MySQL Query Tuning for Dev[Op]s
MySQL 8.0 EXPLAIN ANALYZE
MySQL Indexing : Improving Query Performance Using Index (Covering Index)
New features in Performance Schema 5.7 in action
Using Optimizer Hints to Improve MySQL Query Performance
Using histograms to get better performance
Introduction into MySQL Query Tuning
Optimizer overviewoow2014
Basic MySQL Troubleshooting for Oracle Database Administrators
Query Optimizer in MariaDB 10.4
Lessons for the optimizer from running the TPC-DS benchmark
Ad

Viewers also liked (20)

PDF
Advanced Query Optimizer Tuning and Analysis
PDF
How to Design Indexes, Really
PDF
Need for Speed: MySQL Indexing
PPT
Building High Performance MySql Query Systems And Analytic Applications
PDF
Zurich2007 MySQL Query Optimization
PDF
MySQL Query Tuning for the Squeemish -- Fossetcon Orlando Sep 2014
PDF
MYSQL Query Anti-Patterns That Can Be Moved to Sphinx
PPTX
Tunning sql query
PDF
MySQL Query Optimization
PPT
My sql optimization
PDF
Webinar 2013 advanced_query_tuning
PDF
MySQL Query Optimization.
PDF
Query Optimization with MySQL 5.6: Old and New Tricks - Percona Live London 2013
PDF
Query Optimization with MySQL 5.7 and MariaDB 10: Even newer tricks
PDF
MySQL Query Optimization (Basics)
PDF
Sql query patterns, optimized
PPTX
MySQL Indexing - Best practices for MySQL 5.6
PDF
MySQL Query And Index Tuning
PDF
Percona Live 2012PPT: MySQL Query optimization
PDF
How to Design Indexes, Really
Advanced Query Optimizer Tuning and Analysis
How to Design Indexes, Really
Need for Speed: MySQL Indexing
Building High Performance MySql Query Systems And Analytic Applications
Zurich2007 MySQL Query Optimization
MySQL Query Tuning for the Squeemish -- Fossetcon Orlando Sep 2014
MYSQL Query Anti-Patterns That Can Be Moved to Sphinx
Tunning sql query
MySQL Query Optimization
My sql optimization
Webinar 2013 advanced_query_tuning
MySQL Query Optimization.
Query Optimization with MySQL 5.6: Old and New Tricks - Percona Live London 2013
Query Optimization with MySQL 5.7 and MariaDB 10: Even newer tricks
MySQL Query Optimization (Basics)
Sql query patterns, optimized
MySQL Indexing - Best practices for MySQL 5.6
MySQL Query And Index Tuning
Percona Live 2012PPT: MySQL Query optimization
How to Design Indexes, Really
Ad

Similar to Query Optimization with MySQL 5.6: Old and New Tricks (20)

PPTX
Sql and PL/SQL Best Practices I
PDF
Performance Schema for MySQL Troubleshooting
PDF
Scaling MySQL Strategies for Developers
PDF
Performance Schema for MySQL Troubleshooting
PDF
MySQL Performance Schema in 20 Minutes
PDF
Performance Schema in Action: demo
PDF
sveta smirnova - my sql performance schema in action
PDF
MySQL Performance Schema in Action
PDF
NOCOUG_201311_Fine_Tuning_Execution_Plans.pdf
PDF
What is new in PostgreSQL 14?
PPTX
Top 10 tips for Oracle performance
PDF
MySQL Performance Schema in Action: the Complete Tutorial
PDF
PostgreSQL 9.5 - Major Features
PDF
2018 db-rainer schuettengruber-beating-oracles_optimizer_at_its_own_game-pres...
PDF
Performance Schema for MySQL Troubleshooting
PDF
MySQL 5.7 in a Nutshell
PPT
Top 10 Oracle SQL tuning tips
PDF
Quick Wins
PDF
In Memory Database In Action by Tanel Poder and Kerry Osborne
PDF
Oracle Database In-Memory Option in Action
Sql and PL/SQL Best Practices I
Performance Schema for MySQL Troubleshooting
Scaling MySQL Strategies for Developers
Performance Schema for MySQL Troubleshooting
MySQL Performance Schema in 20 Minutes
Performance Schema in Action: demo
sveta smirnova - my sql performance schema in action
MySQL Performance Schema in Action
NOCOUG_201311_Fine_Tuning_Execution_Plans.pdf
What is new in PostgreSQL 14?
Top 10 tips for Oracle performance
MySQL Performance Schema in Action: the Complete Tutorial
PostgreSQL 9.5 - Major Features
2018 db-rainer schuettengruber-beating-oracles_optimizer_at_its_own_game-pres...
Performance Schema for MySQL Troubleshooting
MySQL 5.7 in a Nutshell
Top 10 Oracle SQL tuning tips
Quick Wins
In Memory Database In Action by Tanel Poder and Kerry Osborne
Oracle Database In-Memory Option in Action

More from MYXPLAIN (10)

PDF
Are You Getting the Best of your MySQL Indexes
PDF
MySQL 5.6 Performance
PDF
Tools and Techniques for Index Design
PDF
Powerful Explain in MySQL 5.6
PDF
The Power of MySQL Explain
PDF
Improving Performance with Better Indexes
PDF
Explaining the MySQL Explain
PDF
Covering indexes
PDF
MySQL Optimizer Overview
PDF
Advanced query optimization
Are You Getting the Best of your MySQL Indexes
MySQL 5.6 Performance
Tools and Techniques for Index Design
Powerful Explain in MySQL 5.6
The Power of MySQL Explain
Improving Performance with Better Indexes
Explaining the MySQL Explain
Covering indexes
MySQL Optimizer Overview
Advanced query optimization

Recently uploaded (20)

PDF
Soil Improvement Techniques Note - Rabbi
PPT
A5_DistSysCh1.ppt_INTRODUCTION TO DISTRIBUTED SYSTEMS
PPTX
Fundamentals of Mechanical Engineering.pptx
PDF
Visual Aids for Exploratory Data Analysis.pdf
PPTX
UNIT - 3 Total quality Management .pptx
PPT
introduction to datamining and warehousing
PDF
Automation-in-Manufacturing-Chapter-Introduction.pdf
PPTX
Information Storage and Retrieval Techniques Unit III
PPT
Occupational Health and Safety Management System
PDF
R24 SURVEYING LAB MANUAL for civil enggi
PPTX
MET 305 2019 SCHEME MODULE 2 COMPLETE.pptx
PPTX
6ME3A-Unit-II-Sensors and Actuators_Handouts.pptx
PPT
INTRODUCTION -Data Warehousing and Mining-M.Tech- VTU.ppt
PDF
BIO-INSPIRED HORMONAL MODULATION AND ADAPTIVE ORCHESTRATION IN S-AI-GPT
PDF
BIO-INSPIRED ARCHITECTURE FOR PARSIMONIOUS CONVERSATIONAL INTELLIGENCE : THE ...
PDF
UNIT no 1 INTRODUCTION TO DBMS NOTES.pdf
PPTX
communication and presentation skills 01
PDF
Exploratory_Data_Analysis_Fundamentals.pdf
PDF
keyrequirementskkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
PPTX
Current and future trends in Computer Vision.pptx
Soil Improvement Techniques Note - Rabbi
A5_DistSysCh1.ppt_INTRODUCTION TO DISTRIBUTED SYSTEMS
Fundamentals of Mechanical Engineering.pptx
Visual Aids for Exploratory Data Analysis.pdf
UNIT - 3 Total quality Management .pptx
introduction to datamining and warehousing
Automation-in-Manufacturing-Chapter-Introduction.pdf
Information Storage and Retrieval Techniques Unit III
Occupational Health and Safety Management System
R24 SURVEYING LAB MANUAL for civil enggi
MET 305 2019 SCHEME MODULE 2 COMPLETE.pptx
6ME3A-Unit-II-Sensors and Actuators_Handouts.pptx
INTRODUCTION -Data Warehousing and Mining-M.Tech- VTU.ppt
BIO-INSPIRED HORMONAL MODULATION AND ADAPTIVE ORCHESTRATION IN S-AI-GPT
BIO-INSPIRED ARCHITECTURE FOR PARSIMONIOUS CONVERSATIONAL INTELLIGENCE : THE ...
UNIT no 1 INTRODUCTION TO DBMS NOTES.pdf
communication and presentation skills 01
Exploratory_Data_Analysis_Fundamentals.pdf
keyrequirementskkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
Current and future trends in Computer Vision.pptx

Query Optimization with MySQL 5.6: Old and New Tricks

  • 1. Query Optimization with MySQL 5.6: Old and New Tricks Jaime Crespo Senior MySQL Instructor Percona Live London 2013 November 11, 2013
  • 2. About This Presentation • Objective #1: - Get faster queries • Reminder of some well-known query optimization techniques - Focus on new 5.6 query features • For other performance tricks with MySQL & InnoDB: - InnoDB Architecture and Performance Optimization with Peter Zaitsev at 2pm 2 www.percona.com
  • 3. Agenda 1. Introduction and Environment Setup 2. Server Update and Configuration 3. Tools for Query Profiling 4. Indexing: Old and New Strategies 5. New Query Planner Features 6. Results and wrap-up 3 www.percona.com
  • 4. Example Platform • Sample LAMP Application - 'My Movies' PHP Script - Example movie database • Distributed as a VirtualBox VM - Import percona_live.ova - User: percona / pass: percona - Make sure httpd and PS are running - Optionally: startxfce4 • Currently no design optimization, no indexes (except PK), no proper query design 4 www.percona.com
  • 5. Query Optimization with MySQL 5.6: Old and New Tricks SERVER UPDATE AND CONFIGURATION 5 www.percona.com 5
  • 6. Basic Configuration Review • InnoDB as the default engine (default in 5.5) • InnoDB File Per Table (default in 5.6) • Larger Buffer Pool and Transaction Log (changed in 5.6) • Row Based Replication and tx_isolation • Performance Schema overhead (enabled by default in 5.6) • InnoDB page checksum (changed in 5.6) • InnoDB Old Blocks time (changed in 5.6) 6 www.percona.com
  • 7. Query Optimization with MySQL 5.6: Old and New Tricks TOOLS FOR QUERY PROFILING 7 www.percona.com 5
  • 8. EXPLAIN • EXPLAIN is most important tool for the MySQL DBA and Developer • It provides: - The query plan strategy - The index(es) to be used - The order of table access - An estimation of the number of rows to be examined! 8 www.percona.com 5
  • 9. EXPLAIN on DML • EXPLAIN is now available also for INSERT, UPDATE and DELETE mysql> EXPLAIN DELETE FROM title WHERE title = 'Pilot'G! ********************* 1. row *********************! id: 1! select_type: SIMPLE! table: title! type: range! possible_keys: PRIMARY,title! key: title! key_len: 77! ref: NULL! rows: 1380! Extra: Using where! 1 row in set (0.00 sec)! 9 www.percona.com 5
  • 10. Structured EXPLAIN mysql> EXPLAIN FORMAT=JSON SELECT COUNT(*) FROM title WHERE (title = 'Pilot' OR production_year > 2010) AND kind_id < 4G *************************** 1. row ***************************! EXPLAIN: {! "query_block": {! "select_id": 1,! "table": {! "table_name": "title",! "access_type": "index_merge",! "possible_keys": [! "title",! "production_year"! ],! "key": "sort_union(title,production_year)",! "key_length": "77,5",! "rows": 4434,! "filtered": 100,! "attached_condition": "(((`imdb`.`title`.`title` = 'Pilot') or (`imdb`.`title`.`production_year` > 2010)) and (`imdb`.`title`.`kind_id` < 4))"! }! }! }! 10 www.percona.com 5
  • 11. Optimizer Trace • Allows profiling of MySQL query planner • It shows not only information about the final query plan (EXPLAIN), but also about other discarded strategies, and its “execution cost” • It can be accessed via the INFORMATION_SCHEMA database • It is off by default 11 www.percona.com 5
  • 12. Checking the Optimizer Trace • mysql> SET optimizer_trace="enabled=on"; • mysql> SELECT COUNT(*) FROM title WHERE (title = 'Pilot' OR production_year > 2010) AND kind_id < 4; +----------+ | COUNT(*) | +----------+ | 3050 | +----------+ 1 row in set (0.01 sec) • mysql> SELECT trace FROM information_schema.optimizer_trace; 12 www.percona.com 5
  • 13. Checking the Optimizer Trace (cont.) { "range_scan_alternatives": [ { "index": "production_year", "ranges": [ "2010 < production_year" ], "index_dives_for_eq_ranges": true, "rowid_ordered": false, "using_mrr": false, "index_only": true, "rows": 3054, "cost": 615.16, "chosen": true } ], "index_to_merge": "production_year", "cumulated_cost": 905.69 } ], "cost_of_reading_ranges": 905.69, "cost_sort_rowid_and_read_disk": 3672.8, "cost_duplicate_removal": 9467.6, "total_cost": 14046 } ], "chosen_range_access_summary": { "range_access_plan": { "type": "index_merge", "index_merge_of": [ 13 www.percona.com 5
  • 14. Limitations of EXPLAIN • It does not really execute the query - Not even subqueries any more • The row statistics can be sometimes very off • It does not give us information about temporary tables (on disk or memory?), subtask timing, query cache hit, etc. 14 www.percona.com 5
  • 15. Handler Statistics • They provide time & memory status-independency: mysql> SHOW SESSION STATUS LIKE 'Hand%'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Handler_commit | 1 | | Handler_delete | 0 | | Handler_discover | 0 | | Handler_external_lock | 2 | | Handler_mrr_init | 0 | | Handler_prepare | 0 | | Handler_read_first | 0 | | Handler_read_key | 1 | | Handler_read_last | 0 | | Handler_read_next | 266 | | Handler_read_prev | 0 | | Handler_read_rnd | 0 | | Handler_read_rnd_next | 0 | | Handler_rollback | 0 | | Handler_savepoint | 0 | | Handler_savepoint_rollback | 0 | | Handler_update | 0 | | Handler_write | 0 | +----------------------------+-------+ 18 rows in set (0.00 sec) 15 www.percona.com 5
  • 16. Slow Query Log and pt-query-digest • Works on all MySQL versions - Specially useful in combination with the extended log statistics in Percona Server SET GLOBAL log_slow_verbosity = 'full'; ! # Time: 130601 8:01:06.058915 # User@Host: root[root] @ localhost [] Id: 42 # Schema: imdb Last_errno: 0 Killed: 0 # Query_time: 7.725616 Lock_time: 0.000328 Rows_sent: 4 Rows_examined: 1543720 Rows_affected: 0 # Bytes_sent: 272 Tmp_tables: 0 Tmp_disk_tables: 0 Tmp_table_sizes: 0 # QC_Hit: No Full_scan: Yes Full_join: No Tmp_table: No Tmp_table_on_disk: No # Filesort: No Filesort_on_disk: No Merge_passes: 0 SET timestamp=1370073666; SELECT id,title,production_year FROM title WHERE title = 'Bambi';! 16 www.percona.com
  • 17. pt-query-digest slow query log general query log tcpdump pt-query-digest report binary log process list input tool output 17 www.percona.com
  • 18. pt-query-digest Report # Profile! # Rank Query ID Response time Calls R/Call Apdx V/M Item! # ==== ================== =============== ===== ======= ==== ===== =======! # 1 0xA8D2BBDE7EBE7822 4932.2992 28.8% 78 63.2346 0.00 5.22 SELECT person_info! # 2 0xFE25DAF5DBB71F49 4205.2160 24.6% 130 32.3478 0.00 3.47 SELECT title! # 3 0x70DAC639802CA233 1299.6269 7.6% 14 92.8305 0.00 0.17 SELECT cast_info! # 4 0xE336B880F4FEC4B8 1184.5101 6.9% 294 4.0289 0.36 2.29 SELECT cast_info! # 5 0x60550B93960F1837 905.1648 5.3% 60 15.0861 0.05 1.33 SELECT name! # 6 0xF46D5C09B4E0CA2F 777.2446 4.5% 16340 0.0476 1.00 0.17 SELECT char_name! # 7 0x09FCFFF0E5BC929F 747.4346 4.4% 130 5.7495 0.53 7.69 SELECT name! # 8 0x9433950BE12B9470 744.1755 4.4% 14368 0.0518 1.00 0.18 SELECT name! # 9 0x4DC0E044996DA715 448.5637 2.6% 130 3.4505 0.65 8.31 SELECT title! # 10 0x09FB72D72ED18E93 361.1904 2.1% 78 4.6306 0.28 1.89 SELECT cast_info title #! # Query 1: 0.02 QPS, 1.40x concurrency, ID 0xA8D2BBDE7EBE7822 at byte 25744265! # Attribute pct total min max avg 95% stddev median! # ============ === ======= ======= ======= ======= ======= ======= =======! # Count 0 78! # Exec time 28 4932s 11s 109s 63s 88s 18s 63s! # Lock time 0 724ms 36us 642ms 9ms 11ms 72ms 93us! # Rows sent 7 12.95k 86 334 170.05 329.68 89.24 136.99! # Rows examine 14 168.99M 2.17M 2.17M 2.17M 2.17M 0 2.17M! # Rows affecte 0 0 0 0 0 0 0 0! # Rows read 7 12.95k 86 334 170.05 329.68 89.24 136.99! # Bytes sent 5 2.39M 16.18k 54.14k 31.43k 54.03k 13.47k 25.99k! 18 www.percona.com
  • 19. performance_schema • Integrated profiling tool • Not new, but improved significately for 5.6 • Substitutes the old PROFILING interface • Can have a 5-10% overhead by default • Can be used to monitor several runtime statistics, among them, query execution statistics of the latest queries: SELECT * FROM performance_schema.events_statements_history_long! 19 www.percona.com
  • 20. Query Optimization with MySQL 5.6: Old and New Tricks INDEXING: OLD AND NEW STRATEGIES 20 www.percona.com 5
  • 21. Advantages of Indexing • Faster Filtering • Faster Column Return (Covering Index) • Faster Ordering • Certain Faster Functions (max, min) 21 www.percona.com
  • 22. Faster Filtering • Indexes allow to return results by reading a fewer number of records - We should minimize the rows value in EXPLAIN/Handlers - const > ref > range > index > ALL! • Usually, only a single index can be used per table access - Compound indexes may provide higher filtering rate 22 www.percona.com
  • 23. Compound Indexes • Column Order in Index Does Matter: - Order by decreasing selectivity - Only one range access per index* 23 www.percona.com
  • 24. Covering Index Technique • Additional columns can be indexed in order to speed-up column retrieval • Specially interesting in n-to-n relationship tables • Not possible if the number or size of columns is too large (e.g. SELECT *, BLOBs) 24 www.percona.com
  • 25. Index Condition Pushdown • Let’s prepare a use case: UPDATE cast_info SET note = left(note, 250); ALTER TABLE cast_info MODIFY note varchar(250), ADD INDEX role_id_note (role_id, note); ! • We want to execute: SELECT * FROM cast_info WHERE role_id = 1 and note like '%Jaime%‘;! 25 www.percona.com 5
  • 26. Without ICP (5.5) mysql> EXPLAIN SELECT * FROM cast_info WHERE role_id = 1 and note like '%Jaime%'G ********** 1. row ********** id: 1 select_type: SIMPLE table: cast_info type: ref possible_keys: role_id_note key: role_id_note key_len: 4 ref: const rows: 11553718 Extra: Using where 1 row in set (0.01 sec)! mysql> SHOW STATUS like 'Hand %';! +----------------------------+---------+! | Variable_name | Value |! +----------------------------+---------+! | Handler_commit | 1 |! | Handler_delete | 0 |! | Handler_discover | 0 |! | Handler_prepare | 0 |! | Handler_read_first | 0 |! | Handler_read_key | 1 |! | Handler_read_last | 0 |! | Handler_read_next | 8346769 |! | Handler_read_prev | 0 |! | Handler_read_rnd | 0 |! | Handler_read_rnd_next | 0 |! | Handler_rollback | 0 |! | Handler_savepoint | 0 |! | Handler_savepoint_rollback | 0 |! | Handler_update | 0 |! | Handler_write | 0 |! +----------------------------+---------+! 16 rows in set (0.00 sec)! 26 www.percona.com 5
  • 27. With ICP (5.6) mysql> EXPLAIN SELECT * FROM cast_info WHERE role_id = 1 and note like '%Jaime%'G ************ 1. row ************ id: 1 select_type: SIMPLE table: cast_info type: ref possible_keys: role_id_note key: role_id_note key_len: 4 ref: const rows: 10259274 Extra: Using index condition 1 row in set (0.00 sec)! mysql> SHOW STATUS like 'Hand%';! +----------------------------+-------+! | Variable_name | Value |! +----------------------------+-------+! | Handler_commit | 1 |! | Handler_delete | 0 |! | Handler_discover | 0 |! | Handler_external_lock | 2 |! | Handler_mrr_init | 0 |! | Handler_prepare | 0 |! | Handler_read_first | 0 |! | Handler_read_key | 1 |! | Handler_read_last | 0 |! | Handler_read_next | 266 |! | Handler_read_prev | 0 |! | Handler_read_rnd | 0 |! | Handler_read_rnd_next | 0 |! | Handler_rollback | 0 |! | Handler_savepoint | 0 |! | Handler_savepoint_rollback | 0 |! | Handler_update | 0 |! | Handler_write | 0 |! +----------------------------+-------+! 18 rows in set (0.00 sec) 27 www.percona.com 5
  • 28. Comparison of ICP Execution • Execution time for this example: • MySQL 5.5: 5.76 sec • MySQL 5.6: 1.09 sec • Over 5x faster • In this example, it would not work with a prefix index (e.g. TEXT/BLOB), as it must search the whole field • Fun fact: if covering technique is tried, it actually runs slower than with ICP for this case/hardware (#68554) 28 www.percona.com 5
  • 29. ICP and Indexing • ICP will change the way we index our tables SELECT * FROM cast_info FORCE INDEX(person_role_id_role_id) WHERE person_role_id > 0 and person_role_id < 150000 and role_id > 1 and role_id < 7;! • For example, a multiple column index can be, in some cases, efficiently used for a range condition on several columns: • Effectiveness is highly dependent on how selective is the second part of the index (an “index scan” is still done at engine level) 29 www.percona.com
  • 30. Index for Sorts • Additional columns can be indexed in order to speed up ordering of rows • Only effective in simple patterns • GROUP BY operations are essentially sorts • They can also be greatly improved with the right indexes in some cases 30 www.percona.com
  • 31. Multi-Range Read (MRR) • Reorders access to table data when using a secondary index on disk for sequential I/O - Like ICP, its efficiency is highly dependent on data distribution and memory contents • It also depends on hardware sequential access (e.g., InnoDB’s read ahead) - May not be useful on SSDs • Not compatible with Using index • Only for range access and equi-joins 31 www.percona.com 5
  • 32. MRR Example • We want to execute: SELECT * FROM cast_info WHERE person_role_id > 0 and person_role_id < 150000; SELECT * FROM cast_info WHERE role_id = 3 and person_role_id > 0 and person_role_id < 500000;! • We will use these indexes, respectively: ALTER TABLE cast_info ADD INDEX person_role_id (person_role_id); ALTER TABLE cast_info ADD INDEX person_role_id_role_id (person_role_id, role_id);! 32 www.percona.com 5
  • 33. Without MRR (5.5) mysql> SHOW STATUS like 'Hand%';! +----------------------------+---------+! | Variable_name | Value |! +----------------------------+---------+! | Handler_commit | 1 |! | Handler_delete | 0 |! | Handler_discover | 0 |! | Handler_prepare | 0 |! | Handler_read_first | 0 |! | Handler_read_key | 1 |! | Handler_read_last | 0 |! | Handler_read_next | 4654312 |! | Handler_read_prev | 0 |! | Handler_read_rnd | 0 |! | Handler_read_rnd_next | 0 |! | Handler_rollback | 0 |! | Handler_savepoint | 0 |! | Handler_savepoint_rollback | 0 |! | Handler_update | 0 |! | Handler_write | 0 |! +----------------------------+---------+! 16 rows in set (0.00 sec) mysql> EXPLAIN SELECT * FROM cast_info FORCE INDEX(person_role_id) WHERE person_role_id > 0 and person_role_id < 150000G *********** 1. row *********** id: 1 select_type: SIMPLE table: cast_info type: range possible_keys: person_role_id key: person_role_id key_len: 5 ref: NULL rows: 8966490 Extra: Using where 1 row in set (0.00 sec)! 33 www.percona.com 5
  • 34. With MRR (5.6) mysql> SHOW STATUS like 'Hand%';! +----------------------------+---------+! | Variable_name | Value |! +----------------------------+---------+! | Handler_commit | 1 |! | Handler_delete | 0 |! | Handler_discover | 0 |! | Handler_external_lock | 4 |! | Handler_mrr_init | 0 |! | Handler_prepare | 0 |! | Handler_read_first | 0 |! | Handler_read_key | 4654313 |! | Handler_read_last | 0 |! | Handler_read_next | 4654312 |! | Handler_read_prev | 0 |! | Handler_read_rnd | 4654312 |! | Handler_read_rnd_next | 0 |! | Handler_rollback | 0 |! | Handler_savepoint | 0 |! | Handler_savepoint_rollback | 0 |! | Handler_update | 0 |! | Handler_write | 0 |! +----------------------------+---------+! 18 rows in set (0.00 sec) mysql> EXPLAIN SELECT * FROM cast_info FORCE INDEX(person_role_id) WHERE person_role_id > 0 and person_role_id < 150000G *********** 1. row *********** id: 1 select_type: SIMPLE table: cast_info type: range possible_keys: person_role_id key: person_role_id key_len: 5 ref: NULL rows: 8966490 Extra: Using index condition; Using MRR 1 row in set (0.00 sec)! 34 www.percona.com 5
  • 35. Comparison of MRR Execution • Execution time for this example: • MySQL 5.5: 4654312 rows in set (1 min 4.79 sec) • MySQL 5.6 (w/MRR, wo/ICP): 4654312 rows in set (48.64 sec) • Consistent 33% execution improvement for this test case • Difficult to see for smaller resultsets • What has changed? • 15% more “read_ahead”s, resulting in a 40% less data reads • Reordering has an overhead, can be tuned with read_rnd_buffer_size 35 www.percona.com 5
  • 36. What’s the Point for the ‘FORCE INDEX’? • For demonstration purposes (full table scan is better here) • Some features are not properly detected yet: SELECT * FROM cast_info FORCE INDEX(person_role_id_role_id) WHERE role_id = 3 and person_role_id > 0 and person_role_id < 500000; • Full table scan (any version): Empty set (8.08 sec) • MySQL 5.5: Empty set (1 min 16.88 sec) • MySQL 5.6 ICP+MRR*: Empty set (0.46 sec) *ICP is responsible for the dramatic change in execution time, not MRR 36 www.percona.com
  • 37. Batched Key Access (BKA) • It retrieves keys in batches and allows MRR usage for JOINs, as an alternative to standard Nested Loop Join execution • Not enabled by default SET optimizer_switch= 'mrr=on,mrr_cost_based=off,batched_key_access=on';! 37 www.percona.com
  • 38. Without BKA (5.5) - EXPLAIN ...! ************* 2. row ************* id: 1! select_type: SIMPLE! table: cast_info! type: ref! possible_keys: person_role_id! key: person_role_id! key_len: 5! ref: imdb.char_name.id! rows: 4! Extra: NULL! 2 rows in set (0.00 sec)! mysql> EXPLAIN SELECT cast_info.note, char_name.name FROM cast_info FORCE index(person_role_id) JOIN char_name ON cast_info.person_role_id = char_name.id WHERE cast_info.person_role_id > 0 and cast_info.person_role_id < 150000 ************ 1. row ************! id: 1! select_type: SIMPLE! table: char_name! type: range! possible_keys: PRIMARY! key: PRIMARY! key_len: 4! ref: NULL! rows: 313782! Extra: Using where! ...! 38 www.percona.com
  • 39. Without BKA (5.5) - Handlers mysql> SHOW STATUS like ‘Hand%’;! +----------------------------+---------+ | Variable_name | Value | +----------------------------+---------+ | Handler_commit | 1 | | Handler_delete | 0 | | Handler_discover | 0 | | Handler_prepare | 0 | | Handler_read_first | 0 | | Handler_read_key | 150000 | | Handler_read_last | 0 | | Handler_read_next | 4804311 | | Handler_read_prev | 0 | | Handler_read_rnd | 0 | | Handler_read_rnd_next | 0 | | Handler_rollback | 0 | | Handler_savepoint | 0 | | Handler_savepoint_rollback | 0 | | Handler_update | 0 | | Handler_write | 0 | +----------------------------+---------+ 18 rows in set (0.00 sec)! 39 www.percona.com
  • 40. With BKA (5.6) - EXPLAIN ...! ************ 2. row ************! id: 1! select_type: SIMPLE! table: cast_info! type: ref! possible_keys: person_role_id! key: person_role_id! key_len: 5! ref: imdb.char_name.id! rows: 4! Extra: Using join buffer (Batched Key Access)! 2 rows in set (0.00 sec)! mysql> EXPLAIN SELECT cast_info.note, char_name.name FROM cast_info FORCE index(person_role_id) JOIN char_name ON cast_info.person_role_id = char_name.id WHERE cast_info.person_role_id > 0 and cast_info.person_role_id < 150000G! ************ 1. row ************! id: 1! select_type: SIMPLE! table: char_name! type: range! possible_keys: PRIMARY! key: PRIMARY! key_len: 4! ref: NULL! rows: 313782! Extra: Using where ...! 40 www.percona.com
  • 41. With BKA (5.6) - Handlers mysql> SHOW STATUS like ‘Hand%’; +----------------------------+---------+ | Variable_name | Value | +----------------------------+---------+ | Handler_commit | 1 | | Handler_delete | 0 | | Handler_discover | 0 | | Handler_external_lock | 6 | | Handler_mrr_init | 1 | | Handler_prepare | 0 | | Handler_read_first | 0 | | Handler_read_key | 4804312 | | Handler_read_last | 0 | | Handler_read_next | 4804311 | | Handler_read_prev | 0 | | Handler_read_rnd | 4654312 | | Handler_read_rnd_next | 0 | | Handler_rollback | 0 | | Handler_savepoint | 0 | | Handler_savepoint_rollback | 0 | | Handler_update | 0 | | Handler_write | 0 | +----------------------------+---------+ 18 rows in set (0.00 sec)! 41 www.percona.com
  • 42. Comparison of BKA Execution • Execution time for this example: • MySQL 5.5: 4654312 rows in set (1 min 6.78 sec) • MySQL 5.6 (w/MRR, w/BKA): 4654312 rows in set (1 min 0.47 sec) • The results are consistent between executions, but the gain is not too big. But if we change the join_buffer_size… • MySQL 5.6 (w/MRR, w/BKA, join_buffer_size = 50M): 4654312 rows in set (19.54 sec) (join_buffer_size does not affect execution time in the 5.5 version) 42 www.percona.com 5
  • 43. Better Index Merge • In this example, it avoids a full table scan: mysql> EXPLAIN SELECT COUNT(*) FROM title WHERE (title = 'Pilot' OR production_year > 2010) AND kind_id < 4G ************************ 1. row ************************ id: 1 select_type: SIMPLE table: title type: index_merge possible_keys: title,production_year key: title,production_year key_len: 77,5 ref: NULL rows: 4434 Extra: Using sort_union(title,production_year); Using where 1 row in set (0.00 sec) (almost all titles have kind_id < 4) • MySQL 5.5: 0.79s – MySQL 5.6: 0.01s 43 www.percona.com 5
  • 44. Extended Secondary Keys • Implicit primary keys inside secondary keys can be used for filtering (ref, range, etc), not only for covering index or sorting. • Requires use_index_extensions=on (default) ALTER TABLE title add index (title(25)); SELECT COUNT(*) FROM title WHERE title = 'Pilot' AND id BETWEEN 1000 AND 1000000; 44 www.percona.com 5
  • 45. Extended Secondary Keys mysql> EXPLAIN SELECT COUNT(*) FROM title WHERE title = 'Pilot' AND id BETWEEN 1000 AND 1000000G ****************** 1. row ******************* id: 1 select_type: SIMPLE table: title type: range possible_keys: PRIMARY,title key: title key_len: 81 ref: NULL rows: 531 Extra: Using index condition; Using where 1 row in set (0.00 sec) 45 www.percona.com 5
  • 46. Duplicate Key Check mysql> alter table title add index (production_year);! Query OK, 0 rows affected (10.08 sec)! Records: 0 Duplicates: 0 Warnings: 0! mysql> alter table title add index (production_year); Query OK, 0 rows affected, 1 warning (5.11 sec) Records: 0 Duplicates: 0 Warnings: 1! ! mysql> show warningsG! ************************* 1. row *************************! Level: Note! Code: 1831! Message: Duplicate index 'production_year_2' defined on the table 'imdb.title'. This is deprecated and will be disallowed in a future release.! 1 row in set (0.00 sec)! 46 www.percona.com 5
  • 47. pt-duplicate-key-checker • It detects duplicate and redundant indexes - Including primary keys at the end of secondary keys on InnoDB tables 47 www.percona.com
  • 48. pt-index-usage & user_stats • Can detect unused indexes - That slow down writes - Can also affect reads! - Wasted memory - Query optimizer woes 48 www.percona.com
  • 49. Query Optimization with MySQL 5.6: Old and New Tricks NEW QUERY PLANNER FEATURES 49 www.percona.com 5
  • 50. Filesort with Short LIMIT • Queries that require a filesort but only the first records are selected can benefit from this optimization: mysql> EXPLAIN select * from movie_info ORDER BY info LIMIT 100G ********************* 1. row ********************* id: 1 select_type: SIMPLE table: movie_info type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 6927988 Extra: Using filesort 1 row in set (0.00 sec) ! Note: Both EXPLAIN and the STATUS Handlers show the same outcome 50 www.percona.com 5
  • 51. Filesort with Short LIMIT (cont.) • SELECT * FROM movie_info ORDER BY info LIMIT 100;! - MySQL 5.5: 20.06 sec - MySQL 5.6 (P_S on): 9.14 sec - MySQL 5.6 (P_S off): 8.51 sec • Over 2x faster. • Exact speed-up may depend on the original sort buffer size 51 www.percona.com 5
  • 52. Subquery Optimization • Late Subquery Materialization - Useful for FROM subqueries if further filtering is done - MySQL may also decide to create its own index on a temporary table on memory SELECT * FROM title JOIN (SELECT * FROM cast_info) AS subselect ON subselect.movie_id = title.id WHERE subselect.id = 1; EXPLAIN: 0.00 sec (vs >2 min in 5.5) EXECUTION: 1m 22 sec (vs > 4 min in 5.5) 52 www.percona.com 5
  • 53. JOINs and Subqueries • Better detection of IN + non-dependent subqueries - Many queries do not need to be converted to a JOIN anymore for a proper execution plan - MySQL decides what is the best strategy: Materialization, Semi-Join, etc. 53 www.percona.com 5
  • 54. That Subquery in 5.5 mysql> EXPLAIN SELECT * FROM title WHERE kind_id IN (SELECT id FROM kind_type WHERE kind='video game')G *************************** 1. row *************************** id: 1 select_type: PRIMARY table: title type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1567676 Extra: Using where An index on title.kind_id won't fix it! *************************** 2. row *************************** id: 2 select_type: DEPENDENT SUBQUERY table: kind_type type: const possible_keys: PRIMARY,kind_id key: kind_id key_len: 47 ref: const rows: 1 Extra: Using index 2 rows in set (0.00 sec)! 54 www.percona.com 5
  • 55. That Subquery in 5.6 mysql> EXPLAIN SELECT * FROM title WHERE kind_id IN (SELECT id FROM kind_type WHERE kind='video game')G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: kind_type type: const possible_keys: PRIMARY,kind key: kind key_len: 47 ref: const rows: 1 Extra: Using index *************************** 2. row *************************** id: 1 select_type: SIMPLE table: title type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1477989 Extra: Using where 2 rows in set (0.00 sec)! An index on title.kind_id can and will be very useful! 55 www.percona.com 5
  • 56. Join Order • Table order algorithm has been optimized, which leads to better query plans when joining many tables 56 www.percona.com 5
  • 57. Persistent Optimizer Statistics • InnoDB index statistics are no longer discarded on server shutdown and recomputed the next time a table is accessed • Controlled by variable: innodb_stats_persistent = ON (default) • Remember that SHOW commands/accessing to I_S do not automatically regenerate statistics by default 57 www.percona.com 5
  • 58. READ ONLY Transactions • START TRANSACTION READ ONLY; - It avoids some overhead of R/W transactions (MVCC) - Automatically used for SELECT in auto_commit - Once started, a new transaction has to be started to perform a write 58 www.percona.com 5
  • 59. Explicit Partition Selection • Usually unnecessary, as MySQL does automatically partition pruning • Can be useful combined with some non-deterministic functions or in some special cases: SELECT count(*) FROM title PARTITION(p01, p02); 59 www.percona.com 5
  • 60. Query Optimization with MySQL 5.6: Old and New Tricks RESULTS AND WRAP-UP 60 www.percona.com 5
  • 61. 5.6 is a Great Release • Many optimizer changes that can potentially improve query execution time • Some of them are transparent, some others require tuning and understanding - Some old tricks and indexing strategies become obsolete in 5.6 • pt-upgrade, from Percona Toolkit, and Percona Playback can be great tools to analyze improvements and regressions 61 www.percona.com
  • 62. Where to Learn More ? • More query and server optimization techniques in our training courses ( http://www.percona.com/training): - Scaling and Optimization for MySQL - Operations and Troubleshooting with MySQL - Moving to MySQL 5.6 - Analysing Queries with Percona Toolkit - Percona Server and Tools (NEW!) • Ask me for a discount (only to PLUK attendants)! 62 www.percona.com
  • 63. Where to Learn More ? (cont.) • Books: • High Performance MySQL, 3rd Edition • SQL Antipatterns • Free MySQL Webinars: • http://www.percona.com/resources/ mysql-webinars 63 www.percona.com
  • 64. Percona Live MySQL Conference and Expo 2014 • For more information and to register: Visit: http://www.percona.com/live/mysql-conference-2014/
  • 65. Thank You! Jaime Crespo jaime.crespo@percona.com 65 wwwww.wpe.prceorncao.cnoam.c om