mysql query tuning 101

40
MySQL Query Tuning 101 Sveta Smirnova, Alexander Rubin April, 16, 2015

Upload: sveta-smirnova

Post on 15-Jul-2015

208 views

Category:

Software


2 download

TRANSCRIPT

Page 1: MySQL Query tuning 101

MySQL Query Tuning 101

Sveta Smirnova, Alexander RubinApril, 16, 2015

Page 2: MySQL Query tuning 101

• Introduction: where to find slow queries

• Indexes: why and how do they work

• All about EXPLAIN

• More tools

• Where to find more information

Agenda2

Page 3: MySQL Query tuning 101

• You develop an application and find out thatsome queries are running slow

• After a while you find some slow queries in theslow query log

• All such queries are always slow• We would not talk about cases when

concurrency affects performance

When you see slow query first3

Page 4: MySQL Query tuning 101

• MySQL has to do some job to execute a selectquery

• In the worst case scenario it will do a full tablescan

• CREATE INDEX• Incorrect index can be used by MySQL

Why query can run slow4

Page 5: MySQL Query tuning 101

select * from table select * from table where id=12

1 2 5 6 7 9 12 16 18 21 22 23 24 25

Full table scan5

Page 6: MySQL Query tuning 101

• When you add index (except for MEMORY)MySQL will use B-Tree

• Support equality and “range” operations

MySQL Indexes6

Page 7: MySQL Query tuning 101

• select * from table where id = 12

• Scan thru the tree and go directly to 1 leaf• Stop

B-Tree: Equality search7

Page 8: MySQL Query tuning 101

• select * from table where id in (6, 12, 18)

• Scan thru the tree and visit many leafs/nodes

B-Tree: Range8

Page 9: MySQL Query tuning 101

• EXPLAIN– Estimates what happens during query

execution– EXTENDED– FORMAT=JSON– PARTITIONS

• INFORMATION SCHEMA.OPTIMIZER TRACE– Real data, collected after query was executed– Advanced topic

How to find out how MySQL uses indexes9

Page 10: MySQL Query tuning 101

mysql> explain select * from t1\G

*************************** 1. row ***************************

...

rows: 12

Extra: NULL

mysql> explain select * from t1 where f2=12\G

*************************** 1. row ***************************

...

key: NULL

...

rows: 12

Extra: Using where

Same number of examined rows for both queries

Effect of indexes: before10

Page 11: MySQL Query tuning 101

mysql> alter table t1 add index(f2);

Query OK, 12 rows affected (0.07 sec)

Records: 12 Duplicates: 0 Warnings: 0

mysql> explain select * from t1 where f2=12\G

*************************** 1. row ***************************

...

key: f2

key_len: 5

ref: const

rows: 1

Extra: NULL

1 row in set (0.00 sec)

Much more effective!Only 1 row examined

Effect of indexes: after11

Page 12: MySQL Query tuning 101

mysql> explain extended select * from t1 join t2 where t1.int_key=1;

+----+-------------+-------+-------+---------------+---------+---------+-------+------+----------+------------------+

| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

+----+-------------+-------+-------+---------------+---------+---------+-------+------+----------+------------------+

| 1 | SIMPLE | t1 | ref | int_key,ik | int_key | 5 | const | 4 | 100.00 | NULL |

| 1 | SIMPLE | t2 | index | NULL | pk | 9 | NULL | 6 | 100.00 | Using index; |

Using join buffer |

(Block Nested Loop) |

+----+-------------+-------+-------+---------------+---------+---------+-------+------+----------+------------------+

2 rows in set, 1 warning (0.00 sec)

Note (Code 1003): /* select#1 */ select ‘test‘.‘t1‘.‘pk‘ AS ‘pk‘,‘test‘.‘t1‘.‘int_key‘ AS ‘int_key‘,‘test‘.‘t2‘.‘pk‘

AS ‘pk‘,‘test‘.‘t2‘.‘int_key‘ AS ‘int_key‘ from ‘test‘.‘t1‘ join ‘test‘.‘t2‘ where (‘test‘.‘t1‘.‘int_key‘ = 1)

Number of select

Select type

Tables, for which information is printed

How data is accessed

Possible keys

Key, which was actually used

Length of the key

Which columns were compared with the index

Number of examined rows

% of filtered rowsrows x filtered / 100 — number of rows,which will be joined with another table

Additional information

Table, for which information is printedProduct of rows here: how many rows in all tables will be accessed

For this example estimated value is 4*6 = 24

Actual (optimized) query as executed by MySQL Server

EXPLAIN: overview12

Page 13: MySQL Query tuning 101

mysql> explain extended select * from t1 join t2 where...

+----+-------------+-------+-------+***

| id | select_type | table | type |***

+----+-------------+-------+-------+***

| 1 | SIMPLE | t1 | ref |***

| 1 | SIMPLE | t2 | index |***

+----+-------------+-------+-------+***

2 rows in set, 1 warning (0.00 sec)

SIMPLE;PRIMARY;UNION;DEPENDENT UNION;UNION RESULT;SUBQUERY;DEPENDENT SUBQUERY;DERIVED;MATERIALIZED

systemconsteq ref

reffulltext

ref or nullindex merge

unique subqueryindex subquery

rangeindexALL

EXPLAIN in details13

Page 14: MySQL Query tuning 101

mysql> explain extended select * from t1 join t2 where t1.int_key=1;

***+---------------+---------+---------+-------+***

***| possible_keys | key | key_len | ref |***

***+---------------+---------+---------+-------+***

***| int_key,ik | int_key | 5 | const |***

***| NULL | pk | 9 | NULL |***

***+---------------+---------+---------+-------+***

2 rows in set, 1 warning (0.00 sec)

Keys, which can be used for resolving the query

Only one key was actually used

Actual length of the key (Important for multiple-column keys)

Which columns were compared with the index

ConstantNumeric in our case

Index usedto resolve rows

EXPLAIN in details: keys14

Page 15: MySQL Query tuning 101

mysql> explain extended select * from t1 join t2 where t1.int_key=1;

***+-------+----------+----------------------------------------------------+

***| rows | filtered | Extra |

***+-------+----------+----------------------------------------------------+

***| 4 | 100.00 | NULL |

***| 6 | 100.00 | Using index; Using join buffer (Block Nested Loop) |

***+-------+----------+----------------------------------------------------+

2 rows in set, 1 warning (0.00 sec)

Number of rows accessed

% of rows filteredAdditional information:how query is resolved

Using filesortUsing temporary

etc.

4X6=24

All rows used

EXPLAIN in details: rows15

Page 16: MySQL Query tuning 101

• MySQL or Percona Server 5.6• Employees test database

– XML: Fusheng Wang and Carlo Zaniolo– SQL: Giuseppe Maxia and Patrick Crews– More information

• Download: https://launchpad.net/test-db/• Install:

– cd employees db– mysql <employees.sql

EXPLAIN type by example: setup16

Page 17: MySQL Query tuning 101

mysql> explain select count(*) from employees where hire_date > ’1995-01-01’\G

********************** 1. row **********************

id: 1

select_type: SIMPLE

table: employees

type: ALL

possible_keys: NULL

key: NULL

key_len: NULL

ref: NULL

rows: 300157

Extra: Using where

1 row in set (0.00 sec)

All rows in the table examinedWorst plan ever!

EXPLAIN type by example: ALL17

Page 18: MySQL Query tuning 101

mysql> explain select count(*) from titles where title=’Senior Engineer’\G

********************** 1. row **********************

id: 1

select_type: SIMPLE

table: titles

type: index

possible_keys: NULL

key: emp_no

key_len: 4

ref: NULL

rows: 444033

Extra: Using where; Using index

1 row in set (0.11 sec)

No row in the table was accessed to resolve the query!Only index used

Still all records in the index were scanned

EXPLAIN type by example: index18

Page 19: MySQL Query tuning 101

• We need to add index to table employees first• mysql> alter table employees \-> add index(hire_date);Query OK, 0 rows affected (3.48 sec)Records: 0 Duplicates: 0 Warnings: 0

EXPLAIN type by example: range19

Page 20: MySQL Query tuning 101

mysql> explain select count(*) from employees where hire_date > ’1995-01-01’\G

********************** 1. row **********************

id: 1

select_type: SIMPLE

table: employees

type: range

possible_keys: hire_date

key: hire_date

key_len: 3

ref: NULL

rows: 68654

Extra: Using where; Using index

1 row in set (0.00 sec)

Only rows from given range used

Compare with ALL:300157/68654 = 4.3720

4 times less rows examined!

EXPLAIN type by example: range20

Page 21: MySQL Query tuning 101

• Consists of two or more columns• Only leftmost part used• mysql> alter table City add keycomb(CountryCode, District, Population),drop key CountryCode;

Combined indexes21

Page 22: MySQL Query tuning 101

mysql> explain select * from City where CountryCode = ’USA’\G

********************** 1. row ******************

table: City

type: ref

possible_keys: comb

key: comb

key_len: 3

ref: const

rows: 273

Uses first field from the comb key

Combined indexes: example 122

Page 23: MySQL Query tuning 101

mysql> explain select * from City where \

-> District = ’California’ and population > 10000\G

********************** 1. row ******************

table: City

type: ALL

possible_keys: NULL

key: NULL

key_len: NULL

ref: NULL

rows: 3868

Can’t use combined index:not a leftmost part

Does not have the CountryCodein the where clause

= can’t use comb index

Combined indexes: example 223

Page 24: MySQL Query tuning 101

• Key len = total size (in bytes) of index parts used• Index: comb(CountryCode, District, Population)

•Explain: Fields:key: comb CountryCode char(3)key len: 3 District char(20)

Population int(11)

3 ->Char(3) ->First field is used

Combined indexes: key len24

Page 25: MySQL Query tuning 101

• Covered index = cover all fields in query• select name from Citywhere CountryCode = ’USA’and District = ’Alaska’ and population > 10000

mysql> alter table City add keycov1(CountryCode, District, population, name);

Uses all fields in the query in particular order

1. Where part 2. Group By/Order (not used now) 3. Select part

Covered indexes25

Page 26: MySQL Query tuning 101

mysql> explain select name from City where CountryCode = ’USA’ \

-> and District = ’Alaska’ and population > 10000\G

*************************** 1. row ***********

table: City

type: range

possible_keys: cov1

key: cov1

key_len: 27

ref: NULL

rows: 1

Extra: Using where; Using index

Covered index is usedMySQL will only use indexWill not go to the data file

EXPLAIN by example: covered indexes26

Page 27: MySQL Query tuning 101

mysql> explain select * from dept_emp where dept_no = ’d005’\G

************************ 1. row ************************

id: 1

select_type: SIMPLE

table: dept_emp

type: ref

possible_keys: dept_no

key: dept_no

key_len: 4

ref: const

rows: 145708

Extra: Using where

1 row in set (0.00 sec)

EXPLAIN type by example: ref27

Page 28: MySQL Query tuning 101

mysql> explain select * from dept_manager

join employees using(emp_no) limit 10\G

************************ 1. row ************************

id: 1

select_type: SIMPLE

table: dept_manager

type: ALL

possible_keys: PRIMARY,emp_no

key: NULL

key_len: NULL

ref: NULL

rows: 24

Extra:

EXPLAIN type by example: eq ref28

Page 29: MySQL Query tuning 101

************************ 2. row ************************

id: 1

select_type: SIMPLE

table: employees

type: eq_ref

possible_keys: PRIMARY

key: PRIMARY

key_len: 4

ref: employees.dept_manager.emp_no

rows: 1

Extra:

2 rows in set (0.00 sec)

EXPLAIN type by example: eq ref29

Page 30: MySQL Query tuning 101

mysql> explain select * from departments where dept_no=’d005’\G

************************ 1. row ************************

id: 1

select_type: SIMPLE

table: departments

type: const

possible_keys: PRIMARY

key: PRIMARY

key_len: 4

ref: const

rows: 1

Extra:

1 row in set (0.00 sec)

EXPLAIN type by example: const30

Page 31: MySQL Query tuning 101

• Limitations– It shows estimates only

• Extensions– EXTENDED– PARTITIONS– FORMAT=JSON

EXPLAIN limitations and extensions31

Page 32: MySQL Query tuning 101

mysql> explain partitions select count(*) \

-> from employees_part where hire_date > ’1991-01-01’\G

************************ 1. row ************************

id: 1

select_type: SIMPLE

table: employees_part

partitions: p1,p2

type: index

possible_keys: NULL

key: PRIMARY

key_len: 7

ref: NULL

rows: 135214

Extra: Using where; Using index

EXPLAIN PARTITIONS32

Page 33: MySQL Query tuning 101

• Gives more information– Real execution path of the query– Pushed conditions– Temporary table and index creation are more

precise– Reflects execution order of ”group by” and

”order by” operations– Displays table materializations

EXPLAIN FORMAT=JSON33

Page 34: MySQL Query tuning 101

mysql> explain format=json insert

into salaries(emp_no, from_date)

select emp_no, min(from_date) from titles

group by emp_no\G

*********************** 1. row ***********************

EXPLAIN: {

"query_block": {

"select_id": 1,

"grouping_operation": {

"using_filesort": false,

"table": {

"table_name": "titles",

EXPLAIN FORMAT=JSON34

Page 35: MySQL Query tuning 101

mysql> explain insert into salaries(emp_no, from_date) \

-> select emp_no, min(from_date) from titles

group by emp_no\G

********************** 1. row **********************

id: 1

select_type: SIMPLE

table: titles

type: index

possible_keys: NULL

key: emp_no

EXPLAIN for DML: not only SELECT35

Page 36: MySQL Query tuning 101

mysql> explain insert into salaries(emp_no, from_date)

select emp_no, min(from_date) from titles

group by emp_no\G

...

key_len: 4

ref: NULL

rows: 444058

Extra: Using index

1 row in set, 2 warnings (0.00 sec)

Warning (Code 1364): Field ’salary’ doesn’t have a default value

Warning (Code 1364): Field ’to_date’ doesn’t have a default value

EXPLAIN for DML: not only SELECT36

Page 37: MySQL Query tuning 101

• Status variables ’Handler %’• Performance schema

– events stages %– events statements %

• INFORMATION SCHEMA.OPTIMIZER TRACE

Other tools37

Page 38: MySQL Query tuning 101

• MySQL User Reference Manual• MySQL Troubleshooting book• High Performance MySQL book• MySQL Performance Blog• Planet MySQL• Troubleshooting Performance Companion slides

More to learn38

Page 39: MySQL Query tuning 101

Thank you!39

Page 40: MySQL Query tuning 101

?

Questions?40