MySQL – innoDB e MyISAM

Quando nós viramos a nova versão do And After 2011 sofremos algun dias com problemas de performance – o MySQL que rodava no servidor funcionava normalmente por algum tempo (aleatório) e o consumo de processamento subia loucamente, o site parava de responder e logo o servidor morria. Um reset, e o ciclo voltava a acontecer…

Testei alguns métodos de cache: geração de html, cache de query mas nada foi muito satisfatório – ou quando resolvia o problema prejudicava um pouco a navegação e usabilidade do site (login, publicação de comentários, etc.).

O @fefurst e um pessoal do Twitter falou para eu verificar como estavam configuradas as tabelas do meu banco e falaram para eu tentar converter para MyISAM (o atual padrão de tabelas do mysql) – mas elas já estavam neste formato.

Alterei tudo para innoDB e o problema de performance acabou – o MySQL parou de derrubar o processador e o tempo de resposta voltou ao normal, ouf!

Principais diferenças entre innoDB e MyISAM

InnoDB usa proteção por registro (row locking) enquanto MyISAM usa proteção por tabelas (table locking), por isso em tabelas que são constantemente alteradas (é o caso de algumas tabelas do And After, com as tabelas de logs, comentários, etc) o InnoDB apresenta uma melhor performance do que o MyISAM – que em outros casos é melhor que InnoDB pois não funciona com transações.

Para tabelas usadas essencialmente para consultas (como tabela de localidades, ou de usuários de um sistema fechado) o MyISAM é o mais recomendado.

Dicas de performance com MySQL

Cache

Outra dica para performance – que o Chrisimplementou aqui no And After – é verificar a existência de querys complexas na sua aplicação e pensar em alguma forma de cache para estas querys. Usamos isso na tagcloud, acompanhem a lógica para confirmar a tagcloud:

  1. Percorrer todas as tags do banco
  2. Verificar quantos posts estão associados a cada tag
  3. Ordenar as tags de acordo com o número de posts que utilizam

Essa query é um pouco lenta, tem alguns innerjoins malucos e não é legal ter ela em quase todas as telas. Uma opção é configurar o cache do próprio MySQL, outra opção (que foi o que fizemos) é transformar esta query em uma rotina e criar uma segunda tabela para a tagcloud OU adicionar uma coluna na tabela de tags que representa a relevância daquela tag (no exemplo, o número de posts que a utilizam).

Indexação de buscas

Esta aí algo que eu não posso falar muito pois ainda não tenho familiaridade: sistemas de indexação de busca. Só conheço o Lucene – sei que funciona com o Zend (EN)  e tem como fazer isso funcionar com o Code Igniter (EN) – mas para aplicações com muita informação é uma opção que deve ser considerada com carinho.

Antes de sair por aí alterando coisas em produção verifique se está tudo certo com o agendamento de backup do seu MySQL.

Referências

PDO – classe para acesso a diversos tipos de banco de dados

Quando comecei a programar em PHP, aprendi como fazer requisições a banco de dados MySQL usando as funções nativas do PHP (mysql_connect(), mysql_query(), etc…), as chamadas MySQL Functions.

Muito se passou, o PHP estava na versão 3, e hoje em dia está na 5 (quando sai a 6, mesmo?!?!). Muitas coisas mudaram, e o PHP possui agora características de Orientação a Objetos muito boas. E com isso foi possível criar uma interface simples e leve para acesso a banco de dados, chamada de PHP Data Object, ou PDO.
O que o PDO faz é ser um intermediador para que vocé possa acessar vários tipos de bases de dados (MySQL, PostGree, Firebird, SQL Server, Oracle, etc…) com a mesma sintaxe, alterando apenas o driver usado na conexão. Ou seja, não é ele quem faz a conversa com a base de dados; ele procura quem é que vai conversar com aquele tipo de base de dados.

Um exemplo prático de insert em uma tabela de um banco MySQL:

<?php
$fullName = $_POST["fullName"];
$childrensName = $_POST["childrensName"];
$age = $_POST["age"];
$cpf = $_POST["cpf"];
$hobbies = $_POST["fullName"];

$db = new PDO("mysql:host=localhost;dbname=mydb", admin", "root");
$stmt = $db->prepare("INSERT INTO user (fullName, childrensName, age, cpf, hobbies) VALUES ("$fullName","$childrensName","$age","$cpf","$hobbies")");
$stmt->execute();
?>

Se fosse necessário usar outro banco, por exemplo um Firebird, seria necesseario alterar apenas a linha que faz a instanciação do objeto PDO, usando o driver adequado.

Esse texto não visa ser um tutorial de como usar, mas sim uma apresentação dessa classe muito útil e, certamente, elegante!

http://br.php.net/manual/en/book.pdo.php