bigue 0 Denunciar post Postado Julho 20, 2011 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
Periscuelo 20 Denunciar post Postado Julho 20, 2011 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
bigue 0 Denunciar post Postado Julho 20, 2011 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
Periscuelo 20 Denunciar post Postado Julho 20, 2011 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
Motta 645 Denunciar post Postado Julho 20, 2011 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
bigue 0 Denunciar post Postado Julho 20, 2011 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
Periscuelo 20 Denunciar post Postado Julho 21, 2011 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