query optimization - percona...how to explain the explain in queries with regular joins, tables are...

74
Query Optimization http://www.percona.com/training/ © 2011 - 2017 Percona, Inc. 1 / 74

Upload: others

Post on 25-Jun-2020

11 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Query Optimizationhttp://www.percona.com/training/

© 2011 - 2017 Percona, Inc. 1 / 74

Page 2: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Table of Contents

1. Query Planning 3. Composite Indexes2. Explaining the EXPLAIN 4. Kitchen Sink

© 2011 - 2017 Percona, Inc. 2 / 74

Page 3: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Query OptimizationQUERY PLANNING

© 2011 - 2017 Percona, Inc. 3 / 74

Page 4: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

About This ChapterThe number one goal is to have faster queries.The process is:

We first ask MySQL what its intended execution planis.If we don't like it, we make a change, and try again...

© 2011 - 2017 Percona, Inc. 4 / 74

Page 5: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

It All Starts with EXPLAINBookmark this manual page:

http://dev.mysql.com/doc/refman/5.7/en/explain-output.html

It is the best source for anyone getting started.

© 2011 - 2017 Percona, Inc. 5 / 74

Page 6: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Example DataIMDB database loaded into InnoDB tables (~5GB)Download it and import it for yourself using imdbpy2sql.py:

http://imdbpy.sourceforge.net

© 2011 - 2017 Percona, Inc. 6 / 74

Page 7: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

First Example CREATE TABLE title ( id int NOT NULL AUTO_INCREMENT, title text NOT NULL, imdb_index varchar(12) DEFAULT NULL, kind_id int NOT NULL, production_year int DEFAULT NULL, imdb_id int DEFAULT NULL, phonetic_code varchar(5) DEFAULT NULL, episode_of_id int DEFAULT NULL, season_nr int DEFAULT NULL, episode_nr int DEFAULT NULL, series_years varchar(49) DEFAULT NULL, md5sum varchar(32) DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

© 2011 - 2017 Percona, Inc. 7 / 74

Page 8: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Find the Title Bambi mysql> EXPLAIN SELECT id,title,production_year FROM title -> WHERE title = 'Bambi' ORDER BY production_year\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 3331824 Extra: Using where; Using filesort 1 row in set, 1 warning (0.00 sec)

© 2011 - 2017 Percona, Inc. 8 / 74

Page 9: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Warning on EXPLAIN?mysql> show warnings\G ************* 1. row ************* Level: Note Code: 1003Message: /* select#1 */ select `imdb`.`title`.`id` AS `id`, `imdb`.`title`.`title` AS `title`, `imdb`.`title`.`production_year` AS `production_year` from `imdb`.`title` where (`imdb`.`title`.`title` = 'Bambi') order by `imdb`.`title`.`production_year` 1 row in set (0.00 sec)

Displays how the optimizer qualifies table and columnnames in the SELECT statementWhat the query looks like after rewriting and optimizationrules are applied

© 2011 - 2017 Percona, Inc. 9 / 74

Page 10: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Aha! Now Add an Indexmysql> ALTER TABLE title ADD INDEX (title);ERROR 1170 (42000): BLOB/TEXT column 'title' used in keyspecification without a key length

© 2011 - 2017 Percona, Inc. 10 / 74

Page 11: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Aha! Now Add an Indexmysql> ALTER TABLE title ADD INDEX (title);ERROR 1170 (42000): BLOB/TEXT column 'title' used in keyspecification without a key length

mysql> ALTER TABLE title ADD INDEX (title(50));Query OK, 0 rows affected (8.09 sec)Records: 0 Duplicates: 0 Warnings: 0

© 2011 - 2017 Percona, Inc. 11 / 74

Page 12: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Let's Revisit mysql> EXPLAIN SELECT id, title, production_year FROM title -> WHERE title = 'Bambi' ORDER by production_year\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title type: ref possible_keys: title key: title key_len: 152 ref: const rows: 4 Extra: Using where; Using filesort 1 row in set, 1 warning (0.00 sec)

ref is equality for comparison, but not PK lookup.Identified 'title' as a candidate index and chose it.Size of the index used.Anticipated number of rows.

© 2011 - 2017 Percona, Inc. 12 / 74

Page 13: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Other Ways of Accessing mysql> EXPLAIN SELECT id, title, production_year FROM title -> WHERE id = 55327\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title type: const possible_keys: PRIMARY key: PRIMARY key_len: 4 ref: const rows: 1 Extra: NULL 1 row in set, 1 warning (0.00 sec)

const: at most, one matching row.Primary Key in InnoDB is always faster than secondary keys.

© 2011 - 2017 Percona, Inc. 13 / 74

Page 14: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

LIKE mysql> EXPLAIN SELECT id, title, production_year FROM title -> WHERE title LIKE 'Bamb%'\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title type: range possible_keys: title key: title key_len: 152 ref: NULL rows: 176 Extra: Using where 1 row in set, 1 warning (0.00 sec)

Type is Range. BETWEEN, IN() and < > are also ranges.Number of rows to examine has increased; we are not specificenough.

© 2011 - 2017 Percona, Inc. 14 / 74

Page 15: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Why is That a Range?We're looking for titles between BambA and BambZ*When we say index in MySQL, we mean trees.

That is, B-Tree/B+Tree/T-Tree.Pretend they're all the same (for simplification).There is only radically different indexing methods forspecialized uses: MEMORY Hash, FULLTEXT, spatialor 3rd party engines.

© 2011 - 2017 Percona, Inc. 15 / 74

Page 16: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

What's That?

© 2011 - 2017 Percona, Inc. 16 / 74

Page 17: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Could This Be a Range? mysql> EXPLAIN SELECT id, title, production_year FROM title -> WHERE title LIKE '%ulp Fiction'\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 3331824 Extra: Using where 1 row in set (0.00 sec)

© 2011 - 2017 Percona, Inc. 17 / 74

Page 18: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

No, We Can't Traverse

© 2011 - 2017 Percona, Inc. 18 / 74

Page 19: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

LIKE 'Z%' mysql> EXPLAIN SELECT id, title, production_year FROM title -> WHERE title LIKE 'Z%'\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title type: range possible_keys: title key: title key_len: 152 ref: NULL rows: 24934 Extra: Using where 1 row in set, 1 warning (0.00 sec)

© 2011 - 2017 Percona, Inc. 19 / 74

Page 20: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

LIKE 'T%' mysql> EXPLAIN SELECT id, title, production_year FROM title -> WHERE title LIKE 'T%'\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title type: ALL possible_keys: title key: NULL key_len: NULL ref: NULL rows: 3331824 Extra: Using where 1 row in set, 1 warning (0.00 sec)

© 2011 - 2017 Percona, Inc. 20 / 74

Page 21: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

MySQL is Reasonably SmartIt dynamically samples the data to choose which is thebetter choice—or in some cases uses static statistics.This helps the optimizer choose:

Which indexes will be useful.Which indexes should be avoided.Which is the better index when there is more than one.

© 2011 - 2017 Percona, Inc. 21 / 74

Page 22: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Why Avoid Indexes?B-Trees work like humans search a phone book;

Use an index if you want just a few rows.Scan cover-to-cover if you want a large percentage.

© 2011 - 2017 Percona, Inc. 22 / 74

Page 23: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Why Avoid Indexes (cont.)Benchmark on a different schema (lower is better):

© 2011 - 2017 Percona, Inc. 23 / 74

Page 24: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

What You Should Take AwayData is absolutely critical.

Development environments should contain sampledata exported from production systems.A few thousands of rows is usually enough for theoptimizer to behave like it does in production.

© 2011 - 2017 Percona, Inc. 24 / 74

Page 25: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

What You Should Take Away (cont.)Input values are absolutely critical.

Between two seemingly identical queries, executionplans may be very different.Just like you test application code functions withseveral values for input arguments.

© 2011 - 2017 Percona, Inc. 25 / 74

Page 26: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Query OptimizationEXPLAINING THE EXPLAIN

© 2011 - 2017 Percona, Inc. 26 / 74

Page 27: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

How to Explain the EXPLAINIn queries with regular joins, tables are read in the orderdisplayed by EXPLAIN.id is a sequential identifier of SELECT statements in thequery.select_type indicates type of SELECT (simple, primary,subquery, union, derived, ...).type says which join type will be used.possible_keys indicates which indexes MySQL canchoose from to find the rows in this table.key indicates which index is used.partitions shows which partitions are being accessed.

© 2011 - 2017 Percona, Inc. 27 / 74

Page 28: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

How to Explain the EXPLAIN (cont.)key_len longest length of the key that was used (whichparts of a composite index are being used).(http://bugs.mysql.com/bug.php?id=83062)ref which columns or constants are compared to the indexto select rows from the table.filtered shows the estimated percentage of table rows thatwill be filtered by the table condition.rows says how many rows have to be examined in orderto execute each step of the query.Extra contains additional information about how MySQLresolves the queryhttp://dev.mysql.com/doc/refman/5.7/en/explain-output.html#explain-extra-information

© 2011 - 2017 Percona, Inc. 28 / 74

Page 29: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Types in EXPLAINThe following slides show possible values for EXPLAINtype, ordered (approximately) from the fastest to theslowest.

FULLTEXT access type (and its special indexes) arenot covered on this section.

© 2011 - 2017 Percona, Inc. 29 / 74

Page 30: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

NULLNot really a plan: no data is returnedSee 'Extra' for a reason

mysql> EXPLAIN SELECT * FROM title WHERE 1 = 2\G

************* 1. row ************* select_type: SIMPLE table: NULL type: NULL possible_keys: NULL key: NULL -- Internally equivalent to key_len: NULL -- SELECT NULL WHERE 0; ref: NULL rows: NULL Extra: Impossible WHERE1 row in set, 1 warning (0.00 sec)

mysql> EXPLAIN SELECT * FROM title WHERE id = -1\G ... type: NULL Extra: no matching row in const table

© 2011 - 2017 Percona, Inc. 30 / 74

Page 31: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

constUsed when comparing a literal with a non-prefixPRIMARY/UNIQUE index.The table has at the most one matching row, which will beread at the start of the query.Because there is only one row, the values can beregarded as constants by the optimizer. *This is very fastsince table is read only once.

© 2011 - 2017 Percona, Inc. 31 / 74

Page 32: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

const (cont.) mysql> EXPLAIN SELECT * FROM title WHERE id = 55327\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title partitions: NULL type: constpossible_keys: PRIMARY key: PRIMARY key_len: 4 ref: const rows: 1 Extra: NULL1 row in set, 1 warning (0.00 sec)

© 2011 - 2017 Percona, Inc. 32 / 74

Page 33: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

eq_refOne row will be read from this table for each combinationof rows from the previous tables.The best possible join type (after const).Used when the whole index is used for the = operator witha UNIQUE or PRIMARY KEY.

© 2011 - 2017 Percona, Inc. 33 / 74

Page 34: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

************* 1. row ************* id: 1 select_type: SIMPLE table: title partitions: NULL type: ref possible_keys: title key: title key_len: 152 ref: const rows: 11 Extra: Using where

************* 2. row ************* id: 1 select_type: SIMPLE table: kind_type partitions: NULL type: eq_ref possible_keys: PRIMARY key: PRIMARY key_len: 4 ref: imdb.title.kind_id rows: 1 Extra: NULL

eq_ref (cont.)mysql> EXPLAIN SELECT title.title, kind_type.kind -> FROM kind_type JOIN title ON kind_type.id = title.kind_id -> WHERE title.title = 'Bambi'\G

© 2011 - 2017 Percona, Inc. 34 / 74

Page 35: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

refSeveral rows will be read from this table for eachcombination of rows from the previous tables.Used if the join uses only a left-most prefix of the index, orif the index is not UNIQUE or PRIMARY KEY.Still not bad, if the index matches only few rows.

© 2011 - 2017 Percona, Inc. 35 / 74

Page 36: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

************* 1. row ************* id: 1 select_type: SIMPLE table: u1 type: indexpossible_keys: first_name key: first_name key_len: 102 ref: NULL rows: 49838 Extra: Using index; Using temporary

************* 2. row ************* id: 1 select_type: SIMPLE table: u2 type: refpossible_keys: first_name key: first_name key_len: 102 ref: imdb.u1.first_name rows: 14 Extra: Using where; Using index; Distinct

ref (cont.)mysql> ALTER TABLE users ADD INDEX (first_name);mysql> EXPLAIN SELECT distinct u1.first_name FROM users u1 JOIN users u2 -> WHERE u1.first_name = u2.first_name and u1.id <> u2.id\G

Can you think of a more efficient way of writing this query?

© 2011 - 2017 Percona, Inc. 36 / 74

Page 37: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

A More Efficient Querymysql> EXPLAIN SELECT first_name FROM users GROUP BY first_name -> HAVING count(first_name) > 1;

************* 1. row ************* id: 1 select_type: SIMPLE table: users type: index possible_keys: first_name key: first_name key_len: 102 ref: NULL rows: 49873 Extra: Using index 1 row in set, 1 warning (0.00 sec)

© 2011 - 2017 Percona, Inc. 37 / 74

Page 38: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

ref_or_nullThis is a join type, like ref, but with the addition thatMySQL does an extra search for rows that contain NULLvalues.This join type optimization is used most often in resolvingsubqueries.

© 2011 - 2017 Percona, Inc. 38 / 74

Page 39: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

ref_or_null (cont.) mysql> ALTER TABLE cast_info ADD INDEX (nr_order); mysql> EXPLAIN SELECT * FROM cast_info -> WHERE nr_order = 1 or nr_order IS NULL\G

************* 1. row ************* id: 1 select_type: SIMPLE table: cast_info type: ref_or_null possible_keys: nr_order key: nr_order key_len: 5 ref: const rows: 26707053 Extra: Using index condition 1 row in set, 1 warning (0.00 sec)

© 2011 - 2017 Percona, Inc. 39 / 74

Page 40: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

index_mergeResults from more than one index are combined either byintersection or union.In this case, the key column contains a list of indexes.

mysql> ALTER TABLE title ADD INDEX (production_year); mysql> EXPLAIN SELECT * FROM title -> WHERE title = 'Dracula' OR production_year = 1922\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title type: index_merge possible_keys: production_year,title key: title,production_year key_len: 152,5 ref: NULL rows: 3503 Extra: Using sort_union(title,production_year); Using where 1 row in set, 1 warning (0.00 sec)

© 2011 - 2017 Percona, Inc. 40 / 74

Page 41: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

rangeOnly rows that are in a given range will be retrieved.An index will still be used to select the rowsThe key_len contains the longest key part that is used.(http://bugs.mysql.com/bug.php?id=83062)The ref column will be NULL for this type.

© 2011 - 2017 Percona, Inc. 41 / 74

Page 42: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

range (cont.)mysql> EXPLAIN SELECT * FROM title -> WHERE title = 'Bambi' OR title = 'Dumbo' -> OR title = 'Cinderella'\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title type: range possible_keys: title key: title key_len: 152 ref: NULL rows: 90 filtered: 100.00 Extra: Using where 1 row in set, 1 warning (0.00 sec)

© 2011 - 2017 Percona, Inc. 42 / 74

Page 43: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

range (cont.)mysql> EXPLAIN SELECT * FROM title -> WHERE title like 'Bamb%';***************** 1. row ***************** id: 1 select_type: SIMPLE table: title type: rangepossible_keys: title key: title key_len: 152 ref: NULL rows: 176 filtered: 100.00 Extra: Using where 1 row in set, 1 warning (0.00 sec)

© 2011 - 2017 Percona, Inc. 43 / 74

Page 44: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

range (cont.)mysql> EXPLAIN SELECT * FROM title -> WHERE production_year BETWEEN 1998 AND 1999\G***************** 1. row ***************** id: 1 select_type: SIMPLE table: title type: rangepossible_keys: production_year key: production_year key_len: 5 ref: NULL rows: 217402 filtered: 100.00 Extra: Using index condition 1 row in set, 1 warning (0.00 sec)

© 2011 - 2017 Percona, Inc. 44 / 74

Page 45: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

indexThe whole index tree is scanned.Otherwise same as ALL.Faster than ALL since the index file is (should be) smallerthan the data file.MySQL can use this join type when the query uses onlycolumns that are part of a single index.

© 2011 - 2017 Percona, Inc. 45 / 74

Page 46: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

index (cont.) mysql> EXPLAIN SELECT count(*), production_year, -> GROUP_CONCAT(DISTINCT kind_id ORDER BY kind_id) as kind_id -> FROM title -> GROUP BY production_year ORDER BY production_year\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title type: index possible_keys: production_year key: production_year key_len: 5 ref: NULL rows: 3244766 filtered: 100.00 Extra: NULL 1 row in set, 1 warning (0.00 sec)

"How many releases per year, and what are their types"

© 2011 - 2017 Percona, Inc. 46 / 74

Page 47: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

ALLA full table scan; the entire table is scanned.Not good even for the first (non-const) table.Very bad for subsequent tables, since it means a full tablescan for each combination of rows from the previoustables is performed.Solutions: rephrase query, add more indexes.

© 2011 - 2017 Percona, Inc. 47 / 74

Page 48: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

ALL (cont.) mysql> ALTER TABLE title ADD INDEX (production_year); mysql> EXPLAIN SELECT * from title -> WHERE MAKEDATE(production_year, 1) >= now() - INTERVAL 1 YEAR\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 3244766 filtered: 100.00 Extra: Using where 1 row in set, 1 warning (0.00 sec)

An index exists on production_year. Whats going on?What is a better solution?

© 2011 - 2017 Percona, Inc. 48 / 74

Page 49: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Much Better mysql> EXPLAIN SELECT * from title -> WHERE production_year >= YEAR(NOW() - INTERVAL 1 YEAR)\G ************* 1. row ************* id: 1 select_type: SIMPLE table: title partitions: NULL type: range possible_keys: production_year key: production_year key_len: 5 ref: NULL rows: 205352 filtered: 100.00 Extra: Using index condition 1 row in set, 1 warning (0.00 sec)

Rule of Thumb: Don't manipulate data already stored

© 2011 - 2017 Percona, Inc. 49 / 74

Page 50: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Extra: What You Would Like to SeeUsing index

Excellent! MySQL can search for the rows directly from the indextree, without reading the actual table (covering index).

DistinctGood! MySQL stops searching for more rows for the combinationafter it has found the first matching row.

Not existsGood! MySQL is able to do a LEFT JOIN optimization, and somerows can be left out.

Using index conditionTables are read by accessing the index and testing to determinewhether to read the full rows. Index information is used to defer("push down") reading full table rows unless it is necessary.

© 2011 - 2017 Percona, Inc. 50 / 74

Page 51: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Extra: What You Don't Like to SeeUsing filesort

Extra sorting pass needed! (Does not imply a file created on disk!)Using temporary

Temporary table needed! (Does not imply temp table on disk.)Typically happens with different ORDER BY and GROUP BY

Using join bufferTables are processed in large batches of rows, instead of by indexedlookups.

Range checked for each record (index map: N)No good index found for direct comparisons.Individual records are separately optimized for index retrieval.This is not fast, but faster than a join with no index at all.

© 2011 - 2017 Percona, Inc. 51 / 74

Page 52: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Query OptimizationCOMPOSITE INDEXES

© 2011 - 2017 Percona, Inc. 52 / 74

Page 53: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

EXERCISE: Add Index(es) to Query mysql> EXPLAIN SELECT * FROM title WHERE title = 'Pilot' AND -> production_year BETWEEN 1997 AND 2009\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title type: ALL possible_keys: NULL -- Removed all indexes for key: NULL -- this exercise. key_len: NULL ref: NULL rows: 3244766 filtered: 1.11 Extra: Using where 1 row in set, 1 warning (0.00 sec)

© 2011 - 2017 Percona, Inc. 53 / 74

Page 54: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

We Are Spoiled for ChoiceWhich one do we choose?

ALTER TABLE title ADD INDEX py (production_year);ALTER TABLE title ADD INDEX t (title(30));ALTER TABLE title ADD INDEX py_t (production_year, title(30));ALTER TABLE title ADD INDEX t_py (title(30), production_year);

Let's try the first one:mysql> ALTER TABLE title ADD INDEX py (production_year);Query OK, 0 rows affected (4.99 sec)Records: 0 Duplicates: 0 Warnings: 0

© 2011 - 2017 Percona, Inc. 54 / 74

Page 55: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Index on (production_year)mysql> EXPLAIN SELECT * FROM title WHERE title = 'Pilot' AND -> production_year BETWEEN 1997 AND 2009\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title type: ALL possible_keys: py key: NULL key_len: NULL ref: NULL rows: 3244766 filtered: 5.00 Extra: Using where 1 row in set, 1 warning (0.00 sec)

© 2011 - 2017 Percona, Inc. 55 / 74

Page 56: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

How about a Smaller Range?mysql> EXPLAIN SELECT * FROM title WHERE title = 'Pilot' AND -> production_year BETWEEN 2008 AND 2009\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title type: range possible_keys: py key: py key_len: 5 ref: NULL rows: 530320 filtered: 10.00 Extra: Using index condition; Using where 1 row in set, 1 warning (0.00 sec)

© 2011 - 2017 Percona, Inc. 56 / 74

Page 57: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Index on (title)mysql> ALTER TABLE title ADD INDEX t (title(30));Query OK, 0 rows affected (6.35 sec)Records: 0 Duplicates: 0 Warnings: 0

mysql> EXPLAIN SELECT * FROM title WHERE title = 'Pilot' AND -> production_year BETWEEN 2008 AND 2009\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title partitions: NULL type: ref possible_keys: py,t key: t key_len: 92 ref: const rows: 3241 filtered: 50.00 Extra: Using where 1 row in set, 1 warning (0.00 sec)

© 2011 - 2017 Percona, Inc. 57 / 74

Page 58: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

************ 1. row ************ id: 1 select_type: SIMPLE table: title type: range possible_keys: py key: py key_len: 5 ref: NULL rows: 530320 filtered: 10.00 Extra: Using index condition; Using where 1 row in set, 1 warning (0.00 sec)

************ 1. row ************ id: 1 select_type: SIMPLE table: title partitions: NULL type: ref possible_keys: py,t key: t key_len: 92 ref: const rows: 3241 filtered: 50.00 Extra: Using where 1 row in set, 1 warning (0.00 sec)

Comparing the twomysql> EXPLAIN SELECT * FROM title WHERE title = 'Pilot' AND -> production_year BETWEEN 2008 AND 2009\G

© 2011 - 2017 Percona, Inc. 58 / 74

Page 59: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Composite IndexesWhich is better?

INDEX py_t (production_year, title)INDEX t_py (title, production_year)

© 2011 - 2017 Percona, Inc. 59 / 74

Page 60: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Index on (py_t)mysql> ALTER TABLE title ADD INDEX py_t (production_year, title(50));Query OK, 0 rows affected (9.11 sec)Records: 0 Duplicates: 0 Warnings: 0

mysql> EXPLAIN SELECT * FROM title WHERE title = 'Pilot' -> AND production_year BETWEEN 2008 AND 2009\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title type: ref possible_keys: py,t,py_t key: t key_len: 92 ref: const rows: 3241 filtered: 16.34 Extra: Using where 1 row in set, 1 warning (0.00 sec)

© 2011 - 2017 Percona, Inc. 60 / 74

Page 61: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Index on (py_t) Visualized

© 2011 - 2017 Percona, Inc. 61 / 74

Page 62: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Index on (t_py)mysql> ALTER TABLE title ADD INDEX t_py (title(30), production_year);Query OK, 0 rows affected (9.11 sec)Records: 0 Duplicates: 0 Warnings: 0

mysql> EXPLAIN SELECT * FROM title WHERE title = 'Pilot' AND -> production_year BETWEEN 2008 AND 2009\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title type: range possible_keys: py,t,py_t,t_py key: t_py key_len: 97 ref: NULL rows: 192 filtered: 100.00 Extra: Using index condition; Using where 1 row in set, 1 warning (0.00 sec)

© 2011 - 2017 Percona, Inc. 62 / 74

Page 63: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Index on (t_py) Visualized

© 2011 - 2017 Percona, Inc. 63 / 74

Page 64: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Composite Index RecommendationsDon't know what order to specify the columns?

RULE: Think about how the equality comparisonsnarrow down the subset of rows to examine. Define theindex so the leftmost columns filter most effectively.EXCEPTION: If you have a range comparison (!=, <, >,BETWEEN, LIKE), those columns should go to theright in the index.

© 2011 - 2017 Percona, Inc. 64 / 74

Page 65: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Recommendations (cont.)Columns after the range-comparison column can't be usedfor filtering in MySQL <5.6We can still push down those extra columns (ICP) to theengine, having a speed up if the condition is very selective

© 2011 - 2017 Percona, Inc. 65 / 74

Page 66: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Query OptimizationKITCHEN SINK

© 2011 - 2017 Percona, Inc. 66 / 74

Page 67: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Indexes are Multi-PurposeSo far indexes have only been used for filtering.

This is the most typical case—don't forget it.There are also other ways MySQL can use indexes:

Avoiding having to sort.Preventing temporary tables.Avoiding reading rows from the tables.

© 2011 - 2017 Percona, Inc. 67 / 74

Page 68: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

The First Example Againmysql> EXPLAIN SELECT id, title, production_year FROM title -> WHERE title = 'Bambi' ORDER BY production_year\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 3244766 filtered: 10.00 Extra: Using where; Using filesort 1 row in set, 1 warning (0.00 sec)

© 2011 - 2017 Percona, Inc. 68 / 74

Page 69: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Index Prevents Sortmysql> ALTER TABLE title ADD INDEX t_py (title(50), production_year);

mysql> EXPLAIN SELECT id, title, production_year FROM title -> WHERE title = 'Bambi' ORDER BY production_year\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title type: ref possible_keys: t_py key: t_py key_len: 92 ref: const rows: 11 filtered: 100.00 Extra: Using where 1 row in set, 1 warning (0.00 sec)

© 2011 - 2017 Percona, Inc. 69 / 74

Page 70: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Temporary Table in Usemysql> EXPLAIN SELECT COUNT(*) AS c, production_year -> FROM title GROUP BY production_year\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1496878 Extra: Using temporary; Using filesort 1 row in set (0.00 sec)

© 2011 - 2017 Percona, Inc. 70 / 74

Page 71: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Full Index Scanmysql> ALTER TABLE title ADD INDEX py (production_year);

mysql> EXPLAIN SELECT COUNT(*) AS c, production_year FROM title -> GROUP BY production_year\G

************* 1. row ************* id: 1 select_type: SIMPLE table: title type: index possible_keys: t_py,py key: py key_len: 5 ref: NULL rows: 3244766 filtered: 100.00 Extra: Using index 1 row in set, 1 warning (0.00 sec)

© 2011 - 2017 Percona, Inc. 71 / 74

Page 72: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Retrieving Limited Columnsmysql> SELECT person_id FROM cast_info WHERE person_role_id = 35722;

What's the difference between indexes on(person_role_id) and (person_role_id, person_id)?

© 2011 - 2017 Percona, Inc. 72 / 74

Page 73: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Retrieving Limited Columns (cont.)mysql> ALTER TABLE cast_info ADD INDEX (person_role_id);

mysql> EXPLAIN SELECT person_id FROM cast_info -> WHERE person_role_id = 35722\G

************* 1. row ************* id: 1 select_type: SIMPLE table: cast_info type: ref possible_keys: person_role_id key: person_role_id key_len: 5 ref: const rows: 38 filtered: 100.00 Extra: NULL 1 row in set, 1 warning (0.00 sec)

© 2011 - 2017 Percona, Inc. 73 / 74

Page 74: Query Optimization - Percona...How to Explain the EXPLAIN In queries with regular joins, tables are read in the order displayed by EXPLAIN. id is a sequential identifier of SELECT

Questions? Thanks!http://www.percona.com/training/

© 2011 - 2017 Percona, Inc. 74 / 74