Sunday, August 22, 2010

Otimizar a performance do MySQL em Linux

Uma das componentes mais importantes na optimização do desempenho de um ambiente LAMP (Linux, Apache, MySQL, PHP/Perl) é definitivamente a componente base de dados, ou seja, o MySQL. É o componente onde a sua correcta configuração pode fazer a maior diferença entre um servidor que fica de rastos com um pequeno pico no tráfego ou um que aguenta incólume.


É possível tornar o MySQL mais rápido de 3 formas:

   1. Hardware mais potente.Aumentar a capacidade do hardware é a mais fácil de todas, mas também a mais dispendiosa e menos eficiente.
   2. Correcta afinação dos parâmetros do MySQL (my.cnf). A correcta definição dos parâmetros permite que a memória disponível no servidor seja distribuída da melhor forma, tentamos pois minimizar que o processo mysqld tenha aceda ao disco. Também informamos a base de dados acerca do tipo de carga a esperar para que o MySQLprepare os seus recursos da forma mais eficiente.
   3. Otimização das consultas SQL. É de extrema importância que as tabelas tenham os índices bem definidos, entre outros aspectos.

Neste artigo mostro uma forma simples e expedita de saber quais os parâmetros e que valores aplicar no my.cnf (ficheiro de configuração do MySQL).


Aplicar o my.cnf mais apropriado ao sistema

Juntamente com todas as instalações do MySQL, vem um conjunto de ficheiros modelo de configuração para vários tipos de servidor. Devemos escolher aquele que é mais indicado para o nosso caso específico.

Os ficheiros modelo são os seguintes:

    * my-huge.cnf (enorme capacidade)
    * my-large.cnf (grande capacidade)
    * my-medium.cnf (média capacidade)
    * my-small.cnf (pequena capacidade)

As definições que vêm por defeito no my.cnf são para um servidor com capacidades muito reduzidas, isto para que, por defeito, o MySQL possa correr em qualquer servidor. Devemos por isso substituir esses parâmetros pelos encontrados num dos ficheiros modelo mais adequado ao nosso tipo de sistema.

Caso não saiba onde se encontram esses ficheiros no sistema pode aplicar o seguinte comando para descobrir a sua localização.

find / -name my-*.cnf

Depois de feitas as alterações deve reiniciar o MySQL e esperar até que ele tenha pelo menos 48 horas de carga.


Instalar e correr o MySQL Performance Tuning Primer Script

Fazer o download do scrip

wget http://day32.com/MySQL/tuning-primer.sh

Tornar o script executável

chmod +x ./tuning-primer.sh

Correr o script

./tuning-primer.sh


Exemplo do relatório para um caso real


-- MYSQL PERFORMANCE TUNING PRIMER --
     - By: Matthew  Montgomery -
MySQL Version 4.1.22-standard-log i686

Uptime = 2 days 7 hrs 2 min 31 sec
Avg. qps = 332
Total Questions = 65843202
Threads Connected = 44

Server has been running for over 48hrs.
It should be safe to follow these recommendations

To find out more information on how each of these
runtime variables effects performance visit:
http://dev.mysql.com/doc/refman/4.1/en/server-sys
tem-variables.html
Visit  http://www.mysql.com/products/enterprise/a
dvisors.html
for info about MySQL's Enterprise Monitoring and
 Advisory Service

SLOW QUERIES
Current long_query_time = 5 sec.
You have 1942348 out of 65843325 that take longer
than 5 sec. to complete
The slow query log is enabled.
Your long_query_time seems to be fine

WORKER THREADS
Current thread_cache_size = 8
Current threads_cached = 7
Current threads_per_sec = 0
Historic threads_per_sec = 0
Your thread_cache_size is fine

MAX CONNECTIONS
Current max_connections = 100
Current threads_connected = 47
Historic max_used_connections = 101
The number of used connections is 101% of  the
configured maximum.
You should raise max_connections

MEMORY USAGE
Max Memory Ever Allocated : 1 G
Configured Max Per-thread Buffers : 1 G
Configured Max Global Buffers : 426 M
Configured Max Memory Limit : 1 G
Physical Memory : 5.94 G
Max memory limit seem to be within
acceptable norms

KEY BUFFER
Current MyISAM index space = 179 M
Current key_buffer_size = 384 M
Key cache miss rate is 1 : 62678
Key buffer fill ratio = 23.00 %
Your key_buffer_size seems to be too high.
Perhaps you can use these resources elsewhere

QUERY CACHE
Query cache is enabled
Current query_cache_size = 32 M
Current query_cache_used = 14 M
Current query_cache_limit = 1 M
Current Query cache Memory fill ratio = 44.98 %
Current query_cache_min_res_unit = 4 K
MySQL won't cache query results that are larger
than  query_cache_limit in size

SORT OPERATIONS
Current sort_buffer_size = 2 M
Current record/read_rnd_buffer_size = 7 M
Sort buffer seems to be fine

JOINS
Current join_buffer_size = 132.00 K
You have had 766426 queries where a join could
not use an index properly
You have had 501 joins without keys that check
for key  usage after each row
You should enable "log-queries-not-using-indexes"
Then look for non indexed joins in the slow query
log.
If you are unable to optimize your queries you
may want to increase your
join_buffer_size to accommodate larger joins
in one pass.
Note! This script will still suggest raising
the  join_buffer_size when
ANY joins not using indexes are found.

OPEN FILES LIMIT
Current open_files_limit = 4166 files
The open_files_limit should typically be set
to at  least 2x-3x
that of table_cache if you have heavy MyISAM usage.
You currently have open more than 75% of your
open_files_limit
You should set a higher value for open_files_limit
in  my.cnf

TABLE CACHE
Current table_cache value = 2028 tables
You have a total of 1652 tables
You have 2028 open tables.
Current table_cache hit rate is 14%,  while 100%
of your table cache is in use
You should probably increase your table_cache

TEMP TABLES
Current max_heap_table_size = 16 M
Current tmp_table_size = 32 M
Of 793662 temp tables, 17% were created on disk
Effective in-memory tmp_table_size is limited to 
max_heap_table_size.
Created disk tmp tables ratio seems fine

TABLE SCANS
Current read_buffer_size = 1 M
Current table scan ratio = 69 : 1
read_buffer_size seems to be fine

TABLE LOCKING
Current Lock Wait ratio = 1 : 44
You may benefit from selective use of InnoDB.
If you have long running SELECT's against
MyISAM tables and perform
frequent updates consider setting
'low_priority_updates=1'



O relatório está dividido em várias secções. No final de cada secção é feita a sugestão se algo deve ser alterado ou se os parâmetros definidos estão corretos.

Finalmente devemos aplicar as sugestões e analisar o comportamento do sistema. Este script poupa muito tempo de análise e interpretação dos imensos parâmetros passíveis de optimização. Este processo deve ser revisto regularmente, principalmente se acontecerem mudanças na quantidade de tráfego a chegar ao sistema.

Alternativa mais demorada

Também é possível fazer este trabalho de otimização de uma forma não automática. Para este efeito recomendo a instalação do mysqlreport e leitura do manual de interpretação do relatório.

Enjoy!

1 comment:

Anonymous said...

Este site é realmente um passo a passo de todas as informações que queria sobre isso e não sabia a quem perguntar. Glimpse aqui, e você definitivamente descobri-lo.