Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como acelerar o select count(*) com group by e where?


Aqui estão várias coisas que eu tentaria, em ordem crescente de dificuldade:

(mais fácil) - Certifique-se de ter o índice de cobertura correto
CREATE INDEX ix_temp ON relations (relation_title, object_title);

Isso deve maximizar o desempenho dado seu esquema existente, já que (a menos que sua versão do otimizador do mySQL seja realmente burra!) deve ser verificado) e cobrirá a consulta para que você não precise tocar no índice clusterizado.

(um pouco mais difícil) - certifique-se de que seus campos varchar sejam os menores possíveis

Um dos desafios de desempenho com índices varchar no MySQL é que, ao processar uma consulta, o tamanho total declarado do campo será puxado para a RAM. Portanto, se você tiver um varchar(256), mas estiver usando apenas 4 caracteres, ainda estará pagando o uso de RAM de 256 bytes enquanto a consulta está sendo processada. Ai! Portanto, se você puder reduzir seus limites de varchar facilmente, isso deve acelerar suas consultas.

(mais difícil) - Normalizar

30% de suas linhas com um único valor de string é um grito claro para normalizar em outra tabela, para que você não esteja duplicando strings milhões de vezes. Considere normalizar em três tabelas e usar IDs inteiros para juntá-las.

Em alguns casos, você pode normalizar nos bastidores e ocultar a normalização com visualizações que correspondem ao nome da tabela atual... .

(mais difícil) - Faça hash de suas colunas de string e indexe os hashes

Se normalizar significa alterar muito código, mas você pode alterar um pouco seu esquema, considere criar hashes de 128 bits para suas colunas de string (usando o função MD5 ). Neste caso (diferente da normalização) você não precisa alterar todas as suas consultas, apenas os INSERTs e alguns dos SELECTs. De qualquer forma, você desejará hash seus campos de string e, em seguida, criar um índice nos hashes, por exemplo.
CREATE INDEX ix_temp ON relations (relation_title_hash, object_title_hash);

Observe que você precisará brincar com o SELECT para ter certeza de que está fazendo o cálculo por meio do índice de hash e não puxando o índice clusterizado (necessário para resolver o valor de texto real de object_title para satisfazer a consulta).

Além disso, se a relação_título tiver um tamanho pequeno de varchar, mas o título do objeto tiver um tamanho longo, você poderá fazer hash apenas de object_title e criar o índice em (relation_title, object_title_hash) .

Observe que essa solução só ajuda se um ou ambos os campos forem muito longos em relação ao tamanho dos hashes.

Observe também que há impactos interessantes de diferenciação de maiúsculas/minúsculas do hash, já que o hash de uma string minúscula não é o mesmo que um hash de uma maiúscula. Portanto, você precisará certificar-se de aplicar a canonização às strings antes de criá-las - em outras palavras, apenas hash em minúsculas se estiver em um banco de dados que não diferencia maiúsculas de minúsculas. Você também pode querer aparar espaços do início ou do fim, dependendo de como seu banco de dados lida com espaços à esquerda/à direita.