Então, isso é o que eu tenho:
Uma tabela simples classes__to_students
:
|class |student|
---------------
Math Alice
Math Bob
Math Peter
Math Anne
Music Bob
Music Chis
Music Debbie
...
Há 1000000 aulas. Cada aluno assiste a 500 aulas. (Analogia ruim, eu sei...) Para testar, há 4.000 alunos no banco de dados (então há 2.000.000 linhas), mas esse banco de dados deve lidar com vários milhões de alunos, é por isso que estou usando um MySQL ndbcluster.
De qualquer forma ... uma consulta como esta:
SELECT student, COUNT(class) as common_classes
FROM classes_table
WHERE class IN (my_subject_list)
GROUP BY student
ORDER BY common_classes DESC
resultando em algo como:
|student |commonClasses|
Brad 6
Melissa 4
Chris 3
Bob 3
...
leva cerca de 1 segundo com um mecanismo InnoDB em um servidor, o que é bom. Em um ndbcluster com 3 datanodes, a mesma consulta leva até 10 segundos, o que é demais. Não sei como o enunciado acima é tratado internamente, mas imagino que haja muita comunicação entre os nós, o que a torna lenta devido à latência. Alguém pode me dizer, o que acontece no cluster quando realizo esta consulta? Como posso torná-lo mais rápido?
Nota: esta é uma pergunta que surgiu depois que postei esta pergunta: https://stackoverflow.com/questions/9095054/how-do-i-compute-a-ranking-with-mysql-stored-procedures Para mais informações, dá uma olhada lá!
Em primeiro lugar, Cluster é um mecanismo de armazenamento. Na verdade, ele não executa consultas porque não fala SQL. É por isso que você usa um servidor MySQL, que analisa suas consultas e envia chamadas de API do mecanismo de armazenamento de baixo nível para os nós de dados do cluster. Os nós de dados sabem como recuperar ou armazenar dados. Ou você pode conversar com os nós de dados diretamente usando as APIs do NDB.
MySQL Cluster tem vários meios de execução de consultas. Eles se resumem a:
Pesquisa de chave primária
Pesquisa de chave exclusiva
Varredura de índice ordenada (ou seja, índices não exclusivos que usam árvores T)
Verificação completa da tabela
Digamos que você tenha 4 nós de dados em seu cluster (NoOfReplicas=2). Isso significa que você tem 2 grupos de nós e cada um tem metade dos dados. O cluster usa um hash na chave primária (a menos que você tenha controlado o particionamento usando os recursos de particionamento 5.1). Portanto, para qualquer tabela, metade das linhas está em um grupo de nós e metade das linhas está em outro grupo de nós.
Agora, para os 4 tipos de execução de consulta. Você pode verificar qual tipo de execução é usado com EXPLAIN. Veja como cada um funciona:
Resumo: as pesquisas de chave primária são as melhores. Se você tiver mais de 2 nós, a taxa de transferência aumenta porque todos os nós estão servindo ativamente diferentes fragmentos de dados. A pesquisa de índice ordenada e as varreduras completas da tabela são feitas em paralelo, portanto, mais nós levam a um melhor desempenho.
Não tenho certeza de qual versão do Cluster você está usando, mas talvez valha a pena dar uma olhada no MySQL Cluster 7.2, que inclui um recurso chamado Adaptive Query Localization - isso empurrou as operações JOIN para os nós de dados onde são executadas em paralelo e em conjuntos locais do dados para melhorar drasticamente o desempenho do JOIN.
Os testes mostraram um desempenho de JOIN 70 vezes maior
Você pode ler mais sobre Cluster 7.2 e AQL aqui: http://dev.mysql.com/tech-resources/articles/mysql-cluster-7.2.html
Há também um Guia de otimização de desempenho aqui (nota, registro necessário): http://mysql.com/why-mysql/white-papers/mysql_wp_cluster_perfomance.php