Pergunta

Eu estou usando Rails e MySQL, e tenho uma pergunta eficiência com base na contagem de linha.

Eu tenho um modelo Project que has_many :donations.

Eu quero contar o número de doadores únicas para um projeto.

É ter um campo na tabela de projects chamado num_donors, e incrementá-lo quando um novo doador é criada uma boa idéia?

Ou é algo como @num_donors = Donor.count(:select => 'DISTINCT user_id') vai ser semelhante ou o mesmo em termos de eficiência, graças à otimização de banco de dados? Será que isto vai me obrigar a criar índices para user_id e quaisquer outros campos que eu quero contar?

Será que a mesma resposta espera para somar o valor total doado?

Foi útil?

Solução

Para responder à pergunta título. Sim, é redundante, mas se você deve fazê-lo depende de sua situação.

A menos que você conhece os problemas de desempenho, calcular as contagens totais e na mosca em seu aplicativo e não armazená-los. Ou seja, não armazenam valores calculados a menos que você não tem outra escolha.

Na maioria das situações, você não terá que recorrer a isso e não deve.

Se você deve armazenar valores calculados, faça o seguinte:

  • Não mantê-lo up-to-date, incrementando-lo. Recalcular a contagem / Total de todos os dados cada vez que você atualizá-lo.
  • Se você não tem um monte de atualizações, colocar o código em um disparador de atualização para manter a contagem / totaliza até à data.
  • O problema com redundância bases de dados é que, quando os números discordar, você não tem certeza de que é autoritária. Adicione ao uma nota documentação que a fonte dados é a fonte autorizada se eles discordam e pode ser substituído.

Outras dicas

Enquanto isso depende do tamanho do seu banco de dados, estes são os tipos de operações que os bancos de dados especializar-se em, então eles devem ser rápido. É provavelmente um caso de otimização prematura aqui - você deve começar por não armazenar os totais, tornando-o mais simples -. E otimizar posteriormente, se necessário

Lembre-se da máxima "Um homem com um relógio sempre sabe a hora Um homem com dois relógios nunca tem certeza.". eu só iria armazenar o número derivado se:

Problemas de desempenho impedi-lo de obter os números obtidos quando você precisa deles (que não deve ser um problema, neste caso, uma vez que a resposta é provável que esteja disponível a partir dos índices)

ou

Você tem razão para acreditar que você está perdendo registros da tabela principal através de erro do programador ou ação do usuário deliberada ou acidental. Nesse caso, você pode usar o seu número derivado de auditar o número atualmente calculado.

As respostas de de Pedro e JohnFx são sólidos, o que você está propondo é a desnormalização do seu esquema de banco de dados, o que pode melhorar o desempenho de leitura, mas em detrimento de gravações, enquanto adicionalmente, colocando o ônus sobre o desenvolvedor (ou DBMS adicionais Clevers) para evitar inconsistências dentro do seu conjunto de dados.

ActiveRecord tem algum construído em funcionalidade para gerenciar automaticamente conta com relações has_many. Confira este Railscast em caches contra .

Você sabe que uma bandeira simples faz a mágica ActiveRecord?

class ThingOwner

# it has a column like
# t.integer things_count, :default => 0

has_many :things, :counter_cache => true

end

Como para a pergunta - sim, com certeza ele é redundante, eu gostaria de acrescentar um tal contador se e única , se a participação da things.count de tempo é muito grande.

Caso contrário, é otimização prematura.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top