Otimização MySQL Bianca Caruso da Paixão
Otimizando queries no MySQL Quando realizamos uma consulta, o MySQL analisa para verificar a possibilidade de otimização. O otimizador de consulta do MySQL tira vantagem dos índices, sempre que possível, mas também usa outras informações. O plano de execução da query pode ser analisado com a declaração  EXPLAIN . Este retorna informações como: Os índices que serão usados Tipos de joins  Estimativa do número de linhas que serão examinadas Possíveis usos do EXPLAIN:  Verificar se escrever uma consulta de forma diferente afeta a decisão quanto ao uso de um índice Verificar se o acréscimo de índices em uma tabela afetam o plano de execução Ex: Usando o índice da chave primária mysql> explain select * from  t1 where id > 100 and id < 1000\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 type: range possible_keys: PRIMARY key: PRIMARY key_len: 4 ref: NULL rows: 561 Extra: Using where 1 row in set (0.00 sec)
Otimizando queries no MySQL Uso do  ANALYZE TABLE Essa função analisa e armazena a distribuição das chaves na tabela.  Durante a análise é gerado um lock de leitura para tabelas MyISAM e BDB e para tabelas INNODB um lock de escrita  MySQL usa a distribuição de chaves armazenada para decidir a ordem das tabelas nos joins. Além disso, pode ser usado para decidir quais índices serão usados em uma tabela para uma determinada query Por default,  statements do ANALYZE TABLE são escritos no binary log, dessa maneira são replicados para o slave  Tente comparar colunas que contenham o  mesmo tipo de dados Quando usar colunas indexadas em comparações, use colunas que são do mesmo tipo. Tipos de dados idênticos proporcionam melhor desempenho que tipos não semelhantes.  Ex: INT é diferente de BIGINT CHAR(10) é considerado igual a CHAR(10) ou VARCHAR(10) Ex2: Primeiro comparando INT com INT e depois INT com BIGINT mysql> select t1.id, t2.id from t2, t1 where t2.id=t1.id; 3345194 rows in set ( 25.73 sec ) mysql> alter table t2 modify id bigint; mysql> select t1.id, t2.id from t2, t1 where t2.id=t1.id; 3345194 rows in set ( 1 min 6.56 sec )
Otimizando queries no MySQL   Tente colocar as  colunas indexadas isoladamente  em expressões de comparação Se usar uma chamada de função em uma coluna, o MySQL não poderá usar o índice, porque terá que computar o valor da expressão para todas as linhas mysql> SELECT count(*) FROM t1 WHERE id < 9874/35; +----------+ | count(*) | +----------+ |  189 | +----------+ 1 row in set ( 0.00 sec ) mysql> SELECT count(*) FROM t1 WHERE id * 35 < 9874; +----------+ | count(*) | +----------+ |  189 | +----------+ 1 row in set ( 1.04 sec )
Otimizando queries no MySQL   Forneça sugestões ao otimizador quando necessário Normalmente, o otimizador determina a ordem na qual irá varrer as tabelas, visando a rápida recuperação das linhas. Entretanto, em alguns casos, ele pode não fazer a melhor escolha.  É possível sobrepor a escolha do otimizador com algumas palavras chaves STRAIGHT_JOIN  força as tabelas a serem unidas pela ordem especificada na cláusula FROM Devemos ordenar as tabelas de forma que a seleção mais restritiva venha em primeiro lugar. Quanto mais cedo reduzirmos a quantidade de linhas candidatas, melhor é a consulta. Ex: SELECT straight_join ... FROM t1, t2, t3 ...; SELECT .... FROM t1 straight_join t2 straight_join t3 ...; FORCE INDEX ,  USE INDEX  ou  IGNORE INDEX  após o nome da tabela na lista de tabelas de uma junção Serve para orientar o servidor como usar os índices de sua preferência  Evite o uso excessivo da conversão de tipos automática do MySQL Supondo um campo de inteiros (id) Ex: SELECT * FROM t1 WHERE id = 6; SELECT * FROM t1 WHERE id = ‘6’; A segunda consulta envolve uma conversão de tipos, o que envolve uma pequena queda de desempenho. Caso a coluna seja indexada, uma comparação que envolve conversão de tipos pode impedir que o índice seja usado.  Não utilizar funcionalidades desatualizadas
Otimizando queries no MySQL   Esvaziar uma tabela com efeitos colaterais mínimos: O  TRUNCATE  é uma operação mais rápida que  DELETE  porque não há necessidade de apagar cada linha individualmente Quando realizado um TRUNCATE, ocorre o drop da tabela e em seguida outra é criada vazia com as mesmas definições. Nesse caso o AUTO_INCREMENT é setado para zero. Tabelas Innodb Caso exista uma FOREIGN KEY que referencia a tabela, o TRUNCATE deleta linha a linha e a constraint é checada em cada linha. Isso é o mesmo que realizar um DELETE sem cláusula WHERE Escolha os  tipos de dados adequados Não defina o tamanho das colunas acima do necessário Se a coluna for indexada, usar valores mais curtos proporcionará um aumento de desempenho Tabelas MyISAM Linhas com comprimento variável serão mais fragmentadas para tabelas nas quais são realizadas muitas operações de exclusão e modificação Tabelas com linhas de comprimento fixo são processadas mais rapidamente e são mais fáceis de reconstruir caso aconteça uma corrupção da tabela, entretanto ocupam mais espaço Tabelas Innodb O formato interno de armazenamento de linhas não trata de forma diferente colunas de comprimento fixo e comprimento variável. O fator desempenho está relacionado ao espaço de armazenamento, dessa maneira, como CHAR ocupa mais espaço Ex:  De INT(11) para MEDIUMINT(7)   mysql> select * from t1;   4195328 rows in set (7.83 sec)   mysql> alter table t1 modify id  MEDIUMINT(7) UNSIGNED NOT NULL;     mysql> select * from t1;     4195328 rows in set (6.89 sec)
Otimizando queries no MySQL   Definir colunas como  NOT NULL Acelera o processamento Requer menos espaço de armazenamento Devemos considerar o uso de colunas  ENUM Podemos substituir uma coluna string com baixa cardinalidade em colunas ENUM Processamento é mais rápido pois interiormente são tratados como valores numéricos Usando o  OPTIMIZE TABLE É aconselhável após remoção de grandes quantidades de dados O OPTIMIZE TABLE  pode ser usado com MyISAM e tabelas BDB, mas só desfragmenta tabelas MyISAM Um método de desfragmentação que funciona para qualquer motor de armazenamento é: Esvaziar a tabela com mysqldump Descartar a tabela Recriá-la usando o arquivo de dump Minimizar o tráfego na rede, selecionando somente os dados necessários Uma consulta SELECT * pode não ser uma boa solução, a menos que tenhamos certeza de que a cláusula WHERE irá restringir os resultados apenas para as linhas desejadas. Se uma query maior é mais eficiente, prefira ela a várias pequenas queries
Otimizando queries no MySQL   Usando o PROCEDURE ANALYSE() É usado para obtermos informações sobre as colunas da tabela.  Uma das saídas é uma sugestão para a otimização dos tipos de dados para cada coluna na tabela Ex:  mysql> select * from t1 procedure analyse()\G *************************** 1. row *************************** Field_name: bianca.t1.id Min_value: 1 Max_value: 4587994 Min_length: 1 Max_length: 7 Empties_or_zeros: 0 Nulls: 0 Avg_value_or_avg_length: 2426342.1562 Std: 0.0000 Optimal_fieldtype: MEDIUMINT(7) UNSIGNED NOT NULL *************************** 2. row *************************** Field_name: bianca.t1.nome Min_value: aaa Max_value: dddd Min_length: 3 Max_length: 5 Empties_or_zeros: 0 Nulls: 0 Avg_value_or_avg_length: 4.0000 Std: NULL Optimal_fieldtype: ENUM('aaa','bbbb','ccccc','dddd') NOT NULL 2 rows in set (6.56 sec)
Otimizando queries no MySQL   Carregando dados  eficientemente Carregamento massivo é mais eficiente do que carregamento linha a linha pois o cache só será descartado após o termino da carga do grupo e não após a carga de cada registro. Ex: LOAD DATA -  4195328 rows affected ( 58.69 sec ) INSERT  -  4195328 rows affected ( 100.92 sec ) A carga é mais rápida quando as tabelas não tiverem índices, pois a cada adição de um registro, o índice deve ser modificado no data file. Declarações SQL mais curtas são mais rápidas do que as longas, pois envolvem menos análise gramatical por parte do servidor Se tivermos que usar INSERT, devemos tentar usar a forma que permite especificar linhas múltiplas em uma única declaração:  Ex: INSERT INTO t1 (nome) VALUES (‘aaaaa’), (‘bbbb’), (‘cccc’), .... Use  INSERT ... ON DUPLICATE KEY update [INSERT IGNORE]  ao invés de selecionar antes, verificar se existe e atualizar com  UPDATE Query Cache O query cache armazena o texto do SELECT junto com o resultado correspondente. Se um statement idêntico é recebido posteriormente, o servidor envia o resultado do query cache ao invés de fazer o parse e o processamento do comando.  É muito útil em ambientes onde as tabelas não mudam muito e há muita query idêntica.  Aumentar muito o query cache pode gerar um overhead para mante-lo. Tamanhos de 10MB geralmente são beneficentes, tamanhos de 100MB já não tem o mesmo efeito.
Otimizando queries no MySQL   Não use  COUNT(*)  em tabelas  INNODB  para cada consulta, faça isso periodicamente e crie/atualize tabelas de resumo. Mas se precisar do total de registros numa consulta, use  SQL_CALC_FOUND_ROWS  e  SELECT FOUND_ROWS()   Ex:  mysql> select count(*) from t1; +----------+ | count(*) | +----------+ |  4195328 | +----------+ 1 row in set (3.67 sec) mysql> SELECT SQL_CALC_FOUND_ROWS * FROM t1 limit 1; mysql> SELECT FOUND_ROWS(); +--------------+ | FOUND_ROWS() | +--------------+ |  4195328 | +--------------+ 1 row in set (0.00 sec)
Otimizando queries no MySQL   Para armazenar data e hora atuais, utilize o tipo de dados  TIMESTAMP  ao invés de  DATETIME . TIMESTAMP armazena 4bytes e DATETIME armazena 8bytes   Uso dos Índices São usados para acelerar procuras por linhas que casam com condições de uma cláusula WHERE ou por linhas que casam com linhas de outras tabelas, quando uma junção é executada Para consultas que usam as funções MIN() ou MAX(), os valores podem ser encontrados sem examinar todas as linhas Para executar operações de ordenação e agrupamento (cláusulas ORDER BY e GROUP BY) Para ler toda a informação necessária em uma consulta Ex: Supondo que uma consulta seleciona valores de uma coluna numérica indexada de uma tabela MyISAM. Nesse caso, o MySQL não precisa ler os valores duas vezes, assim o arquivo de dados não precisa ser consultado, somente o arquivo de índices.  Aconselhável usar em colunas com cardinalidade relativamente alta em relação do número de linhas da tabela (ou seja, colunas com poucos valores duplicados) Índices possuem um melhor processamento em colunas menores Índices menores requer menos acesso a disco Indexar prefixos em colunas CHAR, VARCHAR, BINARY, VARBINARY, BLOB ou TEXT irá economizar espaço no índice e tornará as consultas mais rápidas. Indexar apenas o necessário, pois todo índice adicional ocupa espaço extra em disco e prejudica o desempenho das operações de escrita.  Não crie índices duplicados INNODB  sempre mantém a chave primária como parte de cada índice, então não a crie muito grande   A medida que os dados crescem, os índices mais adequados podem mudar, assim como a estrutura.   ORDER BY  e  LIMIT  funcionam melhor em colunas indexadas
Otimizando queries no MySQL   Evitar ‘%’ no início de queries com  LIKE   Ex:  mysql> select * from t1 where nome like 'aa%'; 1048832 rows in set (6.76 sec) mysql> select * from t1 where nome like '%aa%'; 1048832 rows in set (7.18 sec) JOINs  podem ser mais eficientes que tabelas desnormalizadas. Portanto normalize antes e só “desnormalize” onde for necessário. Evite subqueries e uso de  IN  em cláusulas WHERE, o uso de JOIN pode ser mais eficiente Separar queries muito complexas em outras mais simples  Não utilizar flags booleano  Não use  ORDER BY RAND()  se houver mais de 2000 registros   Escolha o character set apropriado (latin1 é mais rápido que UTF8)   Ex: De Latin1 para UTF8 mysql> select * from t1; 4195328 rows in set (7.83 sec) mysql> alter table t1 default character set = utf8; mysql> select * from t1; 4195328 rows in set (11.75 sec)
Otimizando queries no MySQL   Referências: Top100 SQLPerformanceTips: http :// forge .mysql.com/ wiki /Top10SQLPerformanceTips Arquivo de Configuração (dicas):  http ://docs. cellblue . nl /2007/03/17/ easy -mysql-performance- tweaks / Revista SQL Magazine

MySQL Query Optimization

  • 1.
    Otimização MySQL BiancaCaruso da Paixão
  • 2.
    Otimizando queries noMySQL Quando realizamos uma consulta, o MySQL analisa para verificar a possibilidade de otimização. O otimizador de consulta do MySQL tira vantagem dos índices, sempre que possível, mas também usa outras informações. O plano de execução da query pode ser analisado com a declaração EXPLAIN . Este retorna informações como: Os índices que serão usados Tipos de joins Estimativa do número de linhas que serão examinadas Possíveis usos do EXPLAIN: Verificar se escrever uma consulta de forma diferente afeta a decisão quanto ao uso de um índice Verificar se o acréscimo de índices em uma tabela afetam o plano de execução Ex: Usando o índice da chave primária mysql> explain select * from t1 where id > 100 and id < 1000\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 type: range possible_keys: PRIMARY key: PRIMARY key_len: 4 ref: NULL rows: 561 Extra: Using where 1 row in set (0.00 sec)
  • 3.
    Otimizando queries noMySQL Uso do ANALYZE TABLE Essa função analisa e armazena a distribuição das chaves na tabela. Durante a análise é gerado um lock de leitura para tabelas MyISAM e BDB e para tabelas INNODB um lock de escrita MySQL usa a distribuição de chaves armazenada para decidir a ordem das tabelas nos joins. Além disso, pode ser usado para decidir quais índices serão usados em uma tabela para uma determinada query Por default, statements do ANALYZE TABLE são escritos no binary log, dessa maneira são replicados para o slave Tente comparar colunas que contenham o mesmo tipo de dados Quando usar colunas indexadas em comparações, use colunas que são do mesmo tipo. Tipos de dados idênticos proporcionam melhor desempenho que tipos não semelhantes. Ex: INT é diferente de BIGINT CHAR(10) é considerado igual a CHAR(10) ou VARCHAR(10) Ex2: Primeiro comparando INT com INT e depois INT com BIGINT mysql> select t1.id, t2.id from t2, t1 where t2.id=t1.id; 3345194 rows in set ( 25.73 sec ) mysql> alter table t2 modify id bigint; mysql> select t1.id, t2.id from t2, t1 where t2.id=t1.id; 3345194 rows in set ( 1 min 6.56 sec )
  • 4.
    Otimizando queries noMySQL Tente colocar as colunas indexadas isoladamente em expressões de comparação Se usar uma chamada de função em uma coluna, o MySQL não poderá usar o índice, porque terá que computar o valor da expressão para todas as linhas mysql> SELECT count(*) FROM t1 WHERE id < 9874/35; +----------+ | count(*) | +----------+ | 189 | +----------+ 1 row in set ( 0.00 sec ) mysql> SELECT count(*) FROM t1 WHERE id * 35 < 9874; +----------+ | count(*) | +----------+ | 189 | +----------+ 1 row in set ( 1.04 sec )
  • 5.
    Otimizando queries noMySQL Forneça sugestões ao otimizador quando necessário Normalmente, o otimizador determina a ordem na qual irá varrer as tabelas, visando a rápida recuperação das linhas. Entretanto, em alguns casos, ele pode não fazer a melhor escolha. É possível sobrepor a escolha do otimizador com algumas palavras chaves STRAIGHT_JOIN força as tabelas a serem unidas pela ordem especificada na cláusula FROM Devemos ordenar as tabelas de forma que a seleção mais restritiva venha em primeiro lugar. Quanto mais cedo reduzirmos a quantidade de linhas candidatas, melhor é a consulta. Ex: SELECT straight_join ... FROM t1, t2, t3 ...; SELECT .... FROM t1 straight_join t2 straight_join t3 ...; FORCE INDEX , USE INDEX ou IGNORE INDEX após o nome da tabela na lista de tabelas de uma junção Serve para orientar o servidor como usar os índices de sua preferência Evite o uso excessivo da conversão de tipos automática do MySQL Supondo um campo de inteiros (id) Ex: SELECT * FROM t1 WHERE id = 6; SELECT * FROM t1 WHERE id = ‘6’; A segunda consulta envolve uma conversão de tipos, o que envolve uma pequena queda de desempenho. Caso a coluna seja indexada, uma comparação que envolve conversão de tipos pode impedir que o índice seja usado. Não utilizar funcionalidades desatualizadas
  • 6.
    Otimizando queries noMySQL Esvaziar uma tabela com efeitos colaterais mínimos: O TRUNCATE é uma operação mais rápida que DELETE porque não há necessidade de apagar cada linha individualmente Quando realizado um TRUNCATE, ocorre o drop da tabela e em seguida outra é criada vazia com as mesmas definições. Nesse caso o AUTO_INCREMENT é setado para zero. Tabelas Innodb Caso exista uma FOREIGN KEY que referencia a tabela, o TRUNCATE deleta linha a linha e a constraint é checada em cada linha. Isso é o mesmo que realizar um DELETE sem cláusula WHERE Escolha os tipos de dados adequados Não defina o tamanho das colunas acima do necessário Se a coluna for indexada, usar valores mais curtos proporcionará um aumento de desempenho Tabelas MyISAM Linhas com comprimento variável serão mais fragmentadas para tabelas nas quais são realizadas muitas operações de exclusão e modificação Tabelas com linhas de comprimento fixo são processadas mais rapidamente e são mais fáceis de reconstruir caso aconteça uma corrupção da tabela, entretanto ocupam mais espaço Tabelas Innodb O formato interno de armazenamento de linhas não trata de forma diferente colunas de comprimento fixo e comprimento variável. O fator desempenho está relacionado ao espaço de armazenamento, dessa maneira, como CHAR ocupa mais espaço Ex: De INT(11) para MEDIUMINT(7) mysql> select * from t1; 4195328 rows in set (7.83 sec) mysql> alter table t1 modify id MEDIUMINT(7) UNSIGNED NOT NULL; mysql> select * from t1; 4195328 rows in set (6.89 sec)
  • 7.
    Otimizando queries noMySQL Definir colunas como NOT NULL Acelera o processamento Requer menos espaço de armazenamento Devemos considerar o uso de colunas ENUM Podemos substituir uma coluna string com baixa cardinalidade em colunas ENUM Processamento é mais rápido pois interiormente são tratados como valores numéricos Usando o OPTIMIZE TABLE É aconselhável após remoção de grandes quantidades de dados O OPTIMIZE TABLE pode ser usado com MyISAM e tabelas BDB, mas só desfragmenta tabelas MyISAM Um método de desfragmentação que funciona para qualquer motor de armazenamento é: Esvaziar a tabela com mysqldump Descartar a tabela Recriá-la usando o arquivo de dump Minimizar o tráfego na rede, selecionando somente os dados necessários Uma consulta SELECT * pode não ser uma boa solução, a menos que tenhamos certeza de que a cláusula WHERE irá restringir os resultados apenas para as linhas desejadas. Se uma query maior é mais eficiente, prefira ela a várias pequenas queries
  • 8.
    Otimizando queries noMySQL Usando o PROCEDURE ANALYSE() É usado para obtermos informações sobre as colunas da tabela. Uma das saídas é uma sugestão para a otimização dos tipos de dados para cada coluna na tabela Ex: mysql> select * from t1 procedure analyse()\G *************************** 1. row *************************** Field_name: bianca.t1.id Min_value: 1 Max_value: 4587994 Min_length: 1 Max_length: 7 Empties_or_zeros: 0 Nulls: 0 Avg_value_or_avg_length: 2426342.1562 Std: 0.0000 Optimal_fieldtype: MEDIUMINT(7) UNSIGNED NOT NULL *************************** 2. row *************************** Field_name: bianca.t1.nome Min_value: aaa Max_value: dddd Min_length: 3 Max_length: 5 Empties_or_zeros: 0 Nulls: 0 Avg_value_or_avg_length: 4.0000 Std: NULL Optimal_fieldtype: ENUM('aaa','bbbb','ccccc','dddd') NOT NULL 2 rows in set (6.56 sec)
  • 9.
    Otimizando queries noMySQL Carregando dados eficientemente Carregamento massivo é mais eficiente do que carregamento linha a linha pois o cache só será descartado após o termino da carga do grupo e não após a carga de cada registro. Ex: LOAD DATA - 4195328 rows affected ( 58.69 sec ) INSERT - 4195328 rows affected ( 100.92 sec ) A carga é mais rápida quando as tabelas não tiverem índices, pois a cada adição de um registro, o índice deve ser modificado no data file. Declarações SQL mais curtas são mais rápidas do que as longas, pois envolvem menos análise gramatical por parte do servidor Se tivermos que usar INSERT, devemos tentar usar a forma que permite especificar linhas múltiplas em uma única declaração: Ex: INSERT INTO t1 (nome) VALUES (‘aaaaa’), (‘bbbb’), (‘cccc’), .... Use INSERT ... ON DUPLICATE KEY update [INSERT IGNORE] ao invés de selecionar antes, verificar se existe e atualizar com UPDATE Query Cache O query cache armazena o texto do SELECT junto com o resultado correspondente. Se um statement idêntico é recebido posteriormente, o servidor envia o resultado do query cache ao invés de fazer o parse e o processamento do comando. É muito útil em ambientes onde as tabelas não mudam muito e há muita query idêntica. Aumentar muito o query cache pode gerar um overhead para mante-lo. Tamanhos de 10MB geralmente são beneficentes, tamanhos de 100MB já não tem o mesmo efeito.
  • 10.
    Otimizando queries noMySQL Não use COUNT(*) em tabelas INNODB para cada consulta, faça isso periodicamente e crie/atualize tabelas de resumo. Mas se precisar do total de registros numa consulta, use SQL_CALC_FOUND_ROWS e SELECT FOUND_ROWS() Ex: mysql> select count(*) from t1; +----------+ | count(*) | +----------+ | 4195328 | +----------+ 1 row in set (3.67 sec) mysql> SELECT SQL_CALC_FOUND_ROWS * FROM t1 limit 1; mysql> SELECT FOUND_ROWS(); +--------------+ | FOUND_ROWS() | +--------------+ | 4195328 | +--------------+ 1 row in set (0.00 sec)
  • 11.
    Otimizando queries noMySQL Para armazenar data e hora atuais, utilize o tipo de dados TIMESTAMP ao invés de DATETIME . TIMESTAMP armazena 4bytes e DATETIME armazena 8bytes Uso dos Índices São usados para acelerar procuras por linhas que casam com condições de uma cláusula WHERE ou por linhas que casam com linhas de outras tabelas, quando uma junção é executada Para consultas que usam as funções MIN() ou MAX(), os valores podem ser encontrados sem examinar todas as linhas Para executar operações de ordenação e agrupamento (cláusulas ORDER BY e GROUP BY) Para ler toda a informação necessária em uma consulta Ex: Supondo que uma consulta seleciona valores de uma coluna numérica indexada de uma tabela MyISAM. Nesse caso, o MySQL não precisa ler os valores duas vezes, assim o arquivo de dados não precisa ser consultado, somente o arquivo de índices. Aconselhável usar em colunas com cardinalidade relativamente alta em relação do número de linhas da tabela (ou seja, colunas com poucos valores duplicados) Índices possuem um melhor processamento em colunas menores Índices menores requer menos acesso a disco Indexar prefixos em colunas CHAR, VARCHAR, BINARY, VARBINARY, BLOB ou TEXT irá economizar espaço no índice e tornará as consultas mais rápidas. Indexar apenas o necessário, pois todo índice adicional ocupa espaço extra em disco e prejudica o desempenho das operações de escrita. Não crie índices duplicados INNODB sempre mantém a chave primária como parte de cada índice, então não a crie muito grande A medida que os dados crescem, os índices mais adequados podem mudar, assim como a estrutura. ORDER BY e LIMIT funcionam melhor em colunas indexadas
  • 12.
    Otimizando queries noMySQL Evitar ‘%’ no início de queries com LIKE Ex: mysql> select * from t1 where nome like 'aa%'; 1048832 rows in set (6.76 sec) mysql> select * from t1 where nome like '%aa%'; 1048832 rows in set (7.18 sec) JOINs podem ser mais eficientes que tabelas desnormalizadas. Portanto normalize antes e só “desnormalize” onde for necessário. Evite subqueries e uso de IN em cláusulas WHERE, o uso de JOIN pode ser mais eficiente Separar queries muito complexas em outras mais simples Não utilizar flags booleano Não use ORDER BY RAND() se houver mais de 2000 registros Escolha o character set apropriado (latin1 é mais rápido que UTF8) Ex: De Latin1 para UTF8 mysql> select * from t1; 4195328 rows in set (7.83 sec) mysql> alter table t1 default character set = utf8; mysql> select * from t1; 4195328 rows in set (11.75 sec)
  • 13.
    Otimizando queries noMySQL Referências: Top100 SQLPerformanceTips: http :// forge .mysql.com/ wiki /Top10SQLPerformanceTips Arquivo de Configuração (dicas): http ://docs. cellblue . nl /2007/03/17/ easy -mysql-performance- tweaks / Revista SQL Magazine