Slide 1

Slide 1 text

Optimizando MySQL

Slide 2

Slide 2 text

Marcelo Altmann Té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

Slide 3

Slide 3 text

Agenda > Overview > Configuração > Índices > Tabelas temporárias > Identificação de queries

Slide 4

Slide 4 text

Overview

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

Configuração

Slide 7

Slide 7 text

Configuração - Innodb Buffer Pool

Slide 8

Slide 8 text

Configuração - Innodb Buffer Pool

Slide 9

Slide 9 text

Configuração - Innodb Buffer Pool

Slide 10

Slide 10 text

Configuração - Innodb Buffer Pool

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

Configuração - transaction log (redo log)

Slide 13

Slide 13 text

Configuração - transaction log (redo log)

Slide 14

Slide 14 text

Configuração - transaction log (redo log)

Slide 15

Slide 15 text

Configuração - transaction log (redo log)

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

Configuração ● Thread_cache_size ● Skip-name-resolve ○ [email protected] vs [email protected]

Slide 30

Slide 30 text

Índices

Slide 31

Slide 31 text

Índices - Full table scan CREATE 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;

Slide 32

Slide 32 text

Í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: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 4188 Extra: Using where 1 row in set (0.00 sec)

Slide 33

Slide 33 text

Í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: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 4188 Extra: Using where 1 row in set (0.00 sec)

Slide 34

Slide 34 text

Índices - Left most part ALTER 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: range possible_keys: leftMost key: leftMost key_len: 7 ref: NULL rows: 13 Extra: Using index condition 1 row in set (0.00 sec)

Slide 35

Slide 35 text

Índices - Left most part ALTER 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: range possible_keys: leftMost key: leftMost key_len: 7 ref: NULL rows: 13 Extra: Using index condition 1 row in set (0.00 sec)

Slide 36

Slide 36 text

Índices - Left most part mysql> 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))" } } }

Slide 37

Slide 37 text

Índices - Covered index ALTER 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: range possible_keys: covered key: covered key_len: 7 ref: NULL rows: 13 Extra: Using where; Using index 1 row in set (0.00 sec)

Slide 38

Slide 38 text

Índices - Covered index ALTER 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: range possible_keys: covered key: covered key_len: 7 ref: NULL rows: 13 Extra: Using where; Using index 1 row in set (0.00 sec)

Slide 39

Slide 39 text

Tabelas temporárias

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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 | +-------------------------+-------+

Slide 42

Slide 42 text

Identificação de queries

Slide 43

Slide 43 text

Identificação de queries ● SHOW [FULL] PROCESSLIST ● Slow query log ● performance_schema.events_statements_summary_by_digest

Slide 44

Slide 44 text

Identificação de queries - Processlist ● Mostra as conexões atuais e seus status mysql> 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)

Slide 45

Slide 45 text

Identificação de queries - Slow Query ● Slow_query_log ● Long_query_time = N

Slide 46

Slide 46 text

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: 297918 use 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: 2366291 SET 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: 2366291 SET timestamp=1473370713; SELECT MAX(salary) FROM salaries JOIN employees USING(emp_no) WHERE gender = 'M' GROUP BY emp_no;

Slide 47

Slide 47 text

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;

Slide 48

Slide 48 text

Perguntas ?

Slide 49

Slide 49 text

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