optimizando mysql

49
Optimizando MySQL

Upload: marcelo-altmann

Post on 16-Apr-2017

156 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Optimizando MySQL

Optimizando MySQL

Page 2: Optimizando MySQL

Marcelo AltmannTécnologo em Sistemas para Internet

MySQL DBA @ IEDR

Blogueiro - blog.marceloaltmann.com

Oracle ACE Associate - MySQL

Oracle Certified Professional , MySQL 5.6 Database Administrator

Oracle Certified Professional , MySQL 5 Database Administrator

Oracle Certified Professional , MySQL 5 Developer

Oracle Certified Associate , MySQL 5.0 / 5.1 / 5.5

Page 3: Optimizando MySQL

Agenda> Overview

> Configuração

> Índices

> Tabelas temporárias

> Identificação de queries

Page 4: Optimizando MySQL

Overview

Page 5: Optimizando MySQL

Overview

Fonte: http://www.oracle.com/technetwork/articles/java/mysql-acq-139875.html

Page 6: Optimizando MySQL

Configuração

Page 7: Optimizando MySQL

Configuração - Innodb Buffer Pool

Page 8: Optimizando MySQL

Configuração - Innodb Buffer Pool

Page 9: Optimizando MySQL

Configuração - Innodb Buffer Pool

Page 10: Optimizando MySQL

Configuração - Innodb Buffer Pool

Page 11: Optimizando MySQL

Configuração - Innodb Buffer Pool● Monitorar: SHOW GLOBAL STATUS LIKE ‘Innodb_buffer_pool_read%’ :

○ Innodb_buffer_pool_reads - Leituras feitas direto no disco○ Innodb_buffer_pool_read_requests - Leituras feitas na memória

● Innodb_buffer_pool_size (Padrão: 128M)

● Innodb_buffer_pool_dump_at_shutdown

● innodb_buffer_pool_load_at_startup

Page 12: Optimizando MySQL

Configuração - transaction log (redo log)

Page 13: Optimizando MySQL

Configuração - transaction log (redo log)

Page 14: Optimizando MySQL

Configuração - transaction log (redo log)

Page 15: Optimizando MySQL

Configuração - transaction log (redo log)

Page 16: Optimizando MySQL

Configuração - transaction log (redo log)● Monitorar: SHOW GLOBAL STATUS LIKE ‘Innodb_log_waits’

● Innodb_log_buffer_size

○ Padrão 8M - 5.5 / 5.6 / 5.7.5

○ Padrão 16M - 5.7.6

Page 17: Optimizando MySQL

Configuração - transaction log (redo log)● Innodb_flush_log_at_trx_commit=1

● Padrão (ACID)

Page 18: Optimizando MySQL

Configuração - transaction log (redo log)● Innodb_flush_log_at_trx_commit=1

● Padrão (ACID)

Page 19: Optimizando MySQL

Configuração - transaction log (redo log)● Innodb_flush_log_at_trx_commit=1

● Padrão (ACID)

Page 20: Optimizando MySQL

Configuração - transaction log (redo log)● Innodb_flush_log_at_trx_commit=1

● Padrão (ACID)

Page 21: Optimizando MySQL

Configuração - transaction log (redo log)● Innodb_flush_log_at_trx_commit=1

● Padrão (ACID)

Page 22: Optimizando MySQL

Configuração - transaction log (redo log)● Innodb_flush_log_at_trx_commit=0

Page 23: Optimizando MySQL

Configuração - transaction log (redo log)● Innodb_flush_log_at_trx_commit=0

Page 24: Optimizando MySQL

Configuração - transaction log (redo log)● Innodb_flush_log_at_trx_commit=0

Page 25: Optimizando MySQL

Configuração - transaction log (redo log)● Innodb_flush_log_at_trx_commit=2

Page 26: Optimizando MySQL

Configuração - transaction log (redo log)● Innodb_flush_log_at_trx_commit=2

Page 27: Optimizando MySQL

Configuração - transaction log (redo log)● Innodb_flush_log_at_trx_commit=2

Page 28: Optimizando MySQL

Configuração - transaction log (redo log)● Innodb_flush_log_at_trx_commit=2

Page 29: Optimizando MySQL

Configuração● Thread_cache_size

● Skip-name-resolve

[email protected] vs [email protected]

Page 30: Optimizando MySQL

Índices

Page 31: Optimizando MySQL

Índices - Full table scanCREATE TABLE `city` ( `ID` int(11) NOT NULL AUTO_INCREMENT, `Name` char(35) NOT NULL DEFAULT '', `CountryCode` char(3) NOT NULL DEFAULT '', `District` char(20) NOT NULL DEFAULT '', `Population` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`ID`)) ENGINE=InnoDB AUTO_INCREMENT=4080 DEFAULT CHARSET=latin1;

Page 32: Optimizando MySQL

Índices - Full table scan

mysql> EXPLAIN SELECT Name, Population FROM city WHERE CountryCode='BRA' AND Population > 1000000\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: city type: ALLpossible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 4188 Extra: Using where1 row in set (0.00 sec)

Page 33: Optimizando MySQL

Índices - Full table scan

mysql> EXPLAIN SELECT Name, Population FROM city WHERE CountryCode='BRA' AND Population > 1000000\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: city type: ALLpossible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 4188 Extra: Using where1 row in set (0.00 sec)

Page 34: Optimizando MySQL

Índices - Left most partALTER TABLE city ADD KEY leftMost(CountryCode, Population, District);

mysql> EXPLAIN SELECT Name, Population FROM city WHERE CountryCode='BRA' AND Population > 1000000\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: city type: rangepossible_keys: leftMost key: leftMost key_len: 7 ref: NULL rows: 13 Extra: Using index condition1 row in set (0.00 sec)

Page 35: Optimizando MySQL

Índices - Left most partALTER TABLE city ADD KEY leftMost(CountryCode, Population, District);

mysql> EXPLAIN SELECT Name, Population FROM city WHERE CountryCode='BRA' AND Population > 1000000\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: city type: rangepossible_keys: leftMost key: leftMost key_len: 7 ref: NULL rows: 13 Extra: Using index condition1 row in set (0.00 sec)

Page 36: Optimizando MySQL

Índices - Left most partmysql> EXPLAIN FORMAT=JSON SELECT Name, Population FROM city WHERE CountryCode='BRA' AND Population > 1000000;{ "query_block": { "select_id": 1, "table": { "table_name": "city", "access_type": "range", "possible_keys": [ "CountryCode" ], "key": "CountryCode", "used_key_parts": [ "CountryCode", "Population" ], "key_length": "7", "rows": 13, "filtered": 100, "index_condition": "((`world`.`city`.`CountryCode` = 'BRA') and (`world`.`city`.`Population` > 1000000))" } }}

Page 37: Optimizando MySQL

Índices - Covered indexALTER TABLE city ADD KEY covered (CountryCode, Population, Name);

mysql> EXPLAIN SELECT Name, Population FROM city WHERE CountryCode='BRA' AND Population > 1000000\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: city type: rangepossible_keys: covered key: covered key_len: 7 ref: NULL rows: 13 Extra: Using where; Using index1 row in set (0.00 sec)

Page 38: Optimizando MySQL

Índices - Covered indexALTER TABLE city ADD KEY covered (CountryCode, Population, Name);

mysql> EXPLAIN SELECT Name, Population FROM city WHERE CountryCode='BRA' AND Population > 1000000\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: city type: rangepossible_keys: covered key: covered key_len: 7 ref: NULL rows: 13 Extra: Using where; Using index1 row in set (0.00 sec)

Page 39: Optimizando MySQL

Tabelas temporárias

Page 40: Optimizando MySQL

Tabelas temporárias● GROUP BY

● UNION

● SUBQUERY + WHERE

● Memória: Memory Engine

● Disco:

○ 5.6 - MyIsam Engine

○ 5.7 - Innodb Engine

● Memory Engine:

○ Não tem suporte a campos BLOB / TEXT

● https://dev.mysql.com/doc/refman/5.6/en/internal-temporary-tables.html

Page 41: Optimizando MySQL

Tabelas temporárias● tmp_table_size - tamanho máximo de uma tabela temporária● max_head_table_size - tamanho máximo de uma tabela que utiliza memory engine

● Tamanho tabela temporária:

○ Maior que tmp_table_size ou max_head_table_size = criada em disco● Monitorar:

mysql> SHOW GLOBAL STATUS LIKE 'Created\_tmp%tables';

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

| Variable_name | Value |

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

| Created_tmp_disk_tables | 3 |

| Created_tmp_tables | 17 |

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

Page 42: Optimizando MySQL

Identificação de queries

Page 43: Optimizando MySQL

Identificação de queries● SHOW [FULL] PROCESSLIST

● Slow query log

● performance_schema.events_statements_summary_by_digest

Page 44: Optimizando MySQL

Identificação de queries - Processlist

● Mostra as conexões atuais e seus statusmysql> show processlist;+----+------+-----------+-----------+---------+------+----------------+--------------------------------------------------------------------------------------------------+| Id | User | Host | db | Command | Time | State | Info |+----+------+-----------+-----------+---------+------+----------------+--------------------------------------------------------------------------------------------------+| 8 | root | localhost | employees | Query | 4 | Writing to net | SELECT MAX(salary) FROM salaries JOIN employees USING(emp_no) WHERE gender = 'M' GROUP BY emp_no || 9 | root | localhost | employees | Query | 0 | init | show processlist |+----+------+-----------+-----------+---------+------+----------------+--------------------------------------------------------------------------------------------------+2 rows in set (0.00 sec)

Page 45: Optimizando MySQL

Identificação de queries - Slow Query

● Slow_query_log

● Long_query_time = N

Page 46: Optimizando MySQL

Identificação de queries - Slow Query# Time: 160908 17:38:01# User@Host: root[root] @ localhost [] Id: 2# Query_time: 1.127100 Lock_time: 0.000852 Rows_sent: 1000 Rows_examined: 297918use employees;SET timestamp=1473370681;SELECT d.dept_name AS 'Dept', CONCAT(em.last_name, ' ', em.first_name) AS 'Manager last, first', CONCAT(e.last_name,' ', e.first_name, ' ', t.title) AS 'Employee last, first (title)' FROM dept_manager AS dm LEFT JOIN dept_emp AS de ON de.dept_no = dm.dept_no LEFT JOIN departments AS d ON d.dept_no = dm.dept_no LEFT JOIN employees AS e ON e.emp_no = de.emp_no LEFT JOIN employees AS em ON em.emp_no = dm.emp_no LEFT JOIN titles AS t ON t.emp_no = e.emp_no WHERE dm.emp_no = e.emp_no AND dept_name = 'Sales' OR dept_name = 'Marketing' AND dm.to_date >= '2012-05-07' AND t.to_date > '2012-05-07' AND de.to_date > '2012-05-07' ORDER BY e.last_name, e.first_name limit 1000;# Time: 160908 17:38:27# User@Host: root[root] @ localhost [] Id: 2# Query_time: 4.236115 Lock_time: 0.000377 Rows_sent: 179973 Rows_examined: 2366291SET timestamp=1473370707;SELECT MAX(salary) FROM salaries JOIN employees USING(emp_no) WHERE gender = 'M' GROUP BY emp_no;# Time: 160908 17:38:33# User@Host: root[root] @ localhost [] Id: 2# Query_time: 3.268998 Lock_time: 0.000349 Rows_sent: 179973 Rows_examined: 2366291SET timestamp=1473370713;SELECT MAX(salary) FROM salaries JOIN employees USING(emp_no) WHERE gender = 'M' GROUP BY emp_no;

Page 47: Optimizando MySQL

Identificação de queries - performance schema

● Ativado por padrão desde a versão 5.6.6

● DIGEST:○ SELECT Name, Population FROM city WHERE CountryCode='BRA' AND Population >

1000000;○ SELECT Name, Population FROM city WHERE CountryCode='USA' AND Population >

5000000;○ SELECT Name , Population FROM city WHERE CountryCode = ? AND Population > ?;

● Possibilita identificar queries :○ Não utilizam index:

SELECT DIGEST_TEXT FROM events_statements_summary_by_digest WHERE SUM_NO_INDEX_USED > 0;

○ Usam tabelas temporárias no disco:SELECT DIGEST_TEXT FROM events_statements_summary_by_digest WHERE

SUM_CREATED_TMP_DISK_TABLES > 0;

Page 48: Optimizando MySQL

Perguntas ?

Page 49: Optimizando MySQL

Perguntas ?● https://groups.google.com/group/mysqlbr

● @altmannmarcelo

[email protected]

● pt.planet.mysql.com

● Forum em português - http://forums.mysql.com/list.php?72