Performance, Banco de dados ou fors?

Estou usando Hibernate, e gostaria de saber o seguinte…

Digamos que eu faça uma pesquisa de todos os meus carros que tenho no banco, depois eu quero fazer outra pesquisa, apenas dos carros de uma montadora, o que é mais rapido ??

1° refazer a consulta ao banco de dados, pedindo pra listar apenas os itens da montadora especifica ??
2° filtrar a coleção de carros seguindo o padrão filter conforme é explicado abaixo ??

Obs.: Duvida, o hibernate não vai manter instancias duplicadas com os mesmo dados ?? conciderando que na 1° pesquisa eu teria instancia de todos os carros, e na 2° instancia somente dos carros de uma montadora ?? e que ainda assim vou manter a 1° coleção, e quem sabe depois fazer consulta sobre outras montadoras ?? isso não prejudicaria a memoria da minha aplicação ??

A duvida basica é se ficar consultado o banco para cada filtro é pior que consultar a collection já existente na memoria, e se ficar consultando o banco não duplicaria instnacias de itens já existentes na memoria, o que não ocorre no caso das consultas por filtros

Desde ja agradeço

Abaixo segue a forma de fazer o filtro por Coleções

inteface Filter<T>

public interface Filter<T> { public boolean match (T object); }

class CollectionUtil

[code]import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

public class CollectionUtil {
/**
* Filtra a coleção enviada, de acordo com o filtro passado, permanecendo na coleção
* apenas os itens que atendem ao filtro.
*

* A coleção original enviada será modificada.
* @param O tipo do objeto a ser pesquisado.
* @param candidates a lista de objetos a serem filtrados, que devem ser do tipo T
* @param filter o filtro a ser realizado
* @return A mesma coleção enviada como parametro, que ja terá seus dados filtrados.
/
public static Collection filter(final Collection candidates,
final Filter filter) {
for (Iterator it = candidates.iterator(); it.hasNext(); )
if (!filter.match(it.next()))
it.remove();
return candidates;
}
/
*
* Consulta a coleção enviada, de acordo com o filtro passado, criando uma nova coleção
* com apenas os itens que atendem ao filtro.
*

* A coleção original enviada NÃO será modificada.
* @param O tipo do objeto a ser pesquisado.
* @param candidates a lista de objetos a serem filtrados, que devem ser do tipo T
* @param filter o filtro a ser realizado
* @return Uma nova coleção com apenas os itens que atendem o filtro.
*/
public static List query(final Collection candidates,
final Filter filter) {
List results = new ArrayList(candidates);
for (Iterator it = results.iterator(); it.hasNext(); )
if (!filter.match(it.next()))
it.remove();
return results;
}
}[/code]

Filtro para o caso da montadora

private class MontadoraFilter implements Filter<Carro> { private static final int montadoraId; public MontadoraFilter(final int montadoraId) { this.montadoraId = montadoraId; } public boolean match(Carro carro) { return carro.getMontadora().getId() == montadoraId; } }

Exemplo da aplicação

Collection<Carro> todosOsCarros = Repositories.list(Carro.class); carrosDaChevrolet = CollectionUtils.query(todosOsCarros,new MontadoraFilter(1)); carrosDaVolks = CollectionUtils.query(todosOsCarros,new MontadoraFilter(5)); //Não vou listar como fazer via hibernate pq acredito que todos saibam ^^

trabalhar na memoria é sempre melhor q ficar fazendo acesso a disco desde que vc tenha uma memoria q suporte um cache necessario para suas consultas… mas tb tem q ter um algoritmo bom, pq dependendo da logica usada fica mais lento q qqer coisa

Só que o problema de manter os objetos instanciados em memória é que eles podem ser atualizados no banco e você não ficar sabendo.

Bem, isso só é um problema em ambientes altamente transacionais, como em bancos financeiros. Mas é algo a pensar.

Bem, primeiro, os bons SGBDs já mantém a última consulta em memória, acelerando consultas subsequentes.

Segundo, você pode usar soluções de database cashing, como memcashed, TimesTen, etc.

Terceiro, sim você pode utilizar essa mesma técnica dentro do programa, ela é chamada memoização. O LinkedHashMap quando configurado faz isso. O problema é na hora de distribuir a tua aplicação em vários servidores. Eles tem que saber que o teu usuário e manter a conexão na mesma maquina.

Alterações na lista de Modelos é feita + ou - 1 vez por ano, no inicio do ano, quando são lançados novos modelos…

Esse uso de caso especifico é para quando abre-se o fichario para adciona carros, onde existe um ComboBox com a lista de modelos…
mais vc pode filtrar essa lista de modelos, geral, em apenas carros de um montadora, ou pickapus caminhoes etc…

e assim achar mais facil o modelo que vc quer…

For isso mesmo os carros registrados (que é diferente dos modelos, no exemplo ali eu coloquei carros a frota, mas a minha classe mesmo se chama Modelo), então, mesmo os carros da frota, são raramente incluido e excluido (não é todo dia que se compra um carro), mesmo quando este os forem, é so adcionar um botão refresh, para atualizar a lsita de carros…

Como o usuario vai poder listar todos os carros, so de um tipo so de outro… apenas com clicar de alguns botões, não acho necessario a cada clique carregar os dados do banco, e depois jogar fora, quando o usuario muda o botão …

por isso a pergunta sobre performance

A não ser que o seu programa precise rodar “no talo”, com requisitos de performance extremamente rígidos, configure o hibernate para usar um cache (como o ehCache, por exemplo) e deixe isso por conta dele. A não ser que você tenha milhões de registros no banco, o ganho de desempenho de fazer o filtro na mão não compensa você se sujar com estes detalhes de baixo nível…