Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

bigue

Está correto ou é gambiarra

Recommended Posts

Tenho várias estatísticas que quero mostrar dentro de um site, as mesmas são carregadas diversas vezes e em grande quantidade.

 

Existem usuários e produtos, onde os usuários podem comentar e dar nota para os produtos.

 

Estou salvando os comentários em uma tabela e as notas em outra (usuários podem comentar várias vezes e votar apenas uma).

 

----

 

Situação 1:

Quero listar os usuários e mostrar o nome, quantos produtos comentou e quantos deu nota.

 

SELECT u.id_usuario, u.nome, COUNT(c.id_comentario) AS comentarios, COUNT(n.id_nota) AS notas
FROM usuario u
LEFT JOIN comentario c ON c.id_usuario = u.id_usuario
LEFT JOIN nota n ON n.id_usuario = u.id_usuario
GROUP BY u.id_usuario
ORDER BY comentarios DESC

 

---

 

Situação 2:

Quero listar os produtos e mostrar o nome, quantos comentários recebeu, quantas notas recebeu e a nota média.

 

SELECT p.id_produto, p.nome, COUNT(c.id_comentario) AS comentarios, COUNT(n.id_nota) AS notas, AVG(n.nota) AS media
FROM produto p
LEFT JOIN comentario c ON c.id_produto = p.id_produto
LEFT JOIN nota n ON n.id_produto = p.id_produto
GROUP BY p.id_produto
ORDER BY media DESC

 

---

 

Essas situações se resolvem com um SQL com alguns joins e considerando determinado número de registros ou a necessidade de utilizar um ORDER BY, a consulta está ficando lenta.

 

-------

 

O que pensei para solucionar:

 

Criar triggers nas tabelas de comentario e nota que atualiza um campo existente na tabela de usuários e produtos, ou seja, na tabela de usuários irá existir uma coluna comentarios, toda vez que um comentário for salvo, ele vai calcular o total de comentários e atualizar a tabela usuários, assim quando eu precisar de uma lista conforme as situações citadas acima, precisarei fazer apenas um SQL simples na tabela respectiva.

 

SELECT id_usuario, nome, comentarios, notas FROM usuario WHERE id = 1 ORDER BY comentario DESC;

SELECT id_produto, nome, comentarios, notas, media FROM produto WHERE id = 1 ORDER BY media;

 

---

 

O que estou propondo é gambiarra ou é uma solução considerável?

 

Tentei de "n" formas fazer esses SELECT, minha tabela de produtos possui 200.000 registros e o tempo de retorno é impraticável, caso o que estou propondo seja gambiarra, gostaria de alguma luz quanto a criação dessas querys.

 

Obrigado.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não é questão de ser gambiarra o problema é a performance. Acho que oque não pode é existir 2 informações iguais em lugares diferentes

sem a vital necessidade. Ex: se você ja tem em outra tabela esta quantidade não há porque te-la igualmente em outra tabela.

Quanto a trigger não crie a ilusão de que ela resolve tudo, uma vez que sendo executada também vai consumir performance do banco de dados.

A mesma SQL que você usa para trazer o total de comentários para a aplicação será a mesma que a trigger terá de fazer para atualizar o campo certo?

Isso não vai mudar em nada o desempenho do banco. Muito pelo contrário, transfere a carga da aplicação para o banco de dados executar automaticamente.

Eu acho neste caso que seria valido a aplicação gravar na base de dados este total. Ex: select qtde. Ai você incrementa 1 e faz um update na base.

Tudo isso via aplicação. Assim você teria o dado de uma forma simples, sem queries imensas e nem triggers.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eu acho neste caso que seria valido a aplicação gravar na base de dados este total. Ex: select qtde. Ai você incrementa 1 e faz um update na base.

Tudo isso via aplicação. Assim você teria o dado de uma forma simples, sem queries imensas e nem triggers.

 

Minha idéia era fazer exatamente isso, pegar a quantidade e salvar na base, porém via trigger para não poluir demais os arquivos da aplicação.

 

Qual as vantagens e desvantages de fazer através de uma trigger ou via aplicação?

 

Alguma outra sugestão para a solução desse problema? ;p

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bom se a sua trigger for fazer um update incrementando + 1 assim que alguém gravar um comentário ai fica simples.

Pensei que você fosse fazer um select para contar o total de comentários e ai sim fazer o update. Ai não ajudaria em nada.

Não há gambiarra alguma em fazer uma trigger para atualizar um campo em determinadas circunstancias.

A vantagem da trigger é que ela é feita automaticamente no banco de dados após uma determinada condição sem necessitar

de interação por parte de um aplicativo. Porém a mesma tem de ser usada com sabedoria. Colocar um SELECT dentro de uma

trigger pode ser fatal dependendo das circustancias. A vantagem de se fazer via aplicação é que onde se tem um grande volume

de dados e consultas, o banco fica com um peso a menos visto que o processamento pode ser feito rapidamente pela aplicação

jogando apenas a instrução de INSERT ou UPDATE que são instruções muito mais rapidas doque o SELECT. Mas cada caso é um

caso e tem que ser analisado.

 

Abraços.

Compartilhar este post


Link para o post
Compartilhar em outros sites

SELECT u.id_usuario, u.nome, COUNT(DISTINCT c.id_comentario) AS comentarios, COUNT(DISTINCT  n.id_nota) AS notas
FROM usuario u
LEFT JOIN comentario c ON c.id_usuario = u.id_usuario
LEFT JOIN nota n ON n.id_usuario = u.id_usuario
GROUP BY u.id_usuario
ORDER BY comentarios DESC

 

Nota : O DISTINCT é necessário pois a duas tabelas sendo joinhadas o produto cartesiano distorce a contagem.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bom se a sua trigger for fazer um update incrementando + 1 assim que alguém gravar um comentário ai fica simples.

 

Considerando que a solução adotada fosse essa, na tabela usuario e na tabela produto teria uma coluna 'comentarios', quando um comentário fosse inserido eu incrementaria +1 no respectivo usuário e produto com um UPDATE simples. OK!

 

Pergunto:

Em situações futuras não ficaria complicada a manutenção desse campo diante de regras como:

 

- Não contar comentários e notas de usuários com status = 0 (teria que atualizar a coluna na tabela de produtos toda vez que desativasse um usuário);

- Ao deletar um usuário os comentários que ele deu tb são excluídos (teria que atualizar a coluna na tabela de produtos toda vez que excluisse um usuário);

 

Nessas situações teria que ser feita uma consulta para ver quais produtos o usuário comentou para subtrair o valor respectivo e pensando rápido aqui estou achando que isso vai ser só pra dar dor de cabeça.

 

Já fiz tentativas com VIEWS porém as consultas continuavam lentas mais não custa perguntar:

Existe alguma alternativa utilizando VIEWS que pode ajudar nesse caso?

 

Obrigado.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Nessas situações teria que ser feita uma consulta para ver quais produtos o usuário comentou para subtrair o valor respectivo e pensando rápido aqui estou achando que isso vai ser só pra dar dor de cabeça.

Como eu disse, é nessas situações que fazer o trabalho na aplicação é melhor doque fazer no banco de dados.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.