Clonar ResultSet

Existe alguma forma de clonar ResultSet? Vou explicar o motivo, tenho um ResultSet, onde demoro demais para iterá-lo por completo,logo penso em passar esses ResultSets a threads, que rodaram simultaneas, então preciso manter a referência de posição do ResultSet em cada Thread, logo, só um clone resolveria.

Tu pode usar uma Thread para ir lendo o resultset e outra para ir consumindo o que a primeira thread leu. Estilo produtora e consumidora.

Isso não aceleraria o processo, pois a iteração é rápida, onde pega mais é no consumo dos dados. Assim uma thread atrasa a outra.

http://java.sun.com/j2se/1.5.0/docs/api/javax/sql/rowset/CachedRowSet.html

Procure o título “7.0 Scrolling and Updating” e vai ver como se usa o método “populate”.

sim sim. Mas eu quis me referir a ir colocando as linhas do resultset em memória(Queue).

Uma coisa interessante do CachedRowSet é que ele implementa paginação, e permite ir para frente e para trás, mesmo que o ResultSet que você usou para alimentar o CachedRowSet só permita ir para frente.

Então, eu tentei esse CachedRowSet, assim como você havia me dito em outro tópico, mas ele não funciona de forma satisfatória, ele demora demais e pega muito espaço em memória, pois ele copia além dos dados, toda a estruturado banco de dados, com chaves,tabelasm constraints, etc.

Se ele está ocupando muito espaço em memória, sua consulta deve retornar muitas linhas. É isso?

olá

o acesso ao resultset é sequencial, portanto, passe a referencia dele paras as thread e as deixe consumindo os dados.

thingol, sim, a intenção é retornar muitos dados, mas o custo benefício do CachedRowSet, está muito baixo no meu caso pelo menos.

giulianocosta não posso passar o mesmo ResultSet, pois como as Threads não necessariamente rodam sequencialmente, poderiam ocasionar a perda de registros. Exemplo: uma thread da next() e para, ai vem outra e dá next, terei um registro duplicado e um será pulado.

thingol, sim, a intenção é retornar muitos dados, mas o custo benefício do CachedRowSet, está muito baixo no meu caso pelo menos.

giulianocosta não posso passar o mesmo ResultSet, pois como as Threads não necessariamente rodam sequencialmente, poderiam ocasionar a perda de registros. Exemplo: uma thread da next() e para, ai vem outra e dá next, terei um registro duplicado e um será pulado.

Uma coisa meio tediosa que vejo muito aqui é a seguinte: o pessoal costuma simplesmente criar um List<AlgumaCoisa> a partir de um ResultSet, até para poder ter aqueles recursos (de ir para frente, para trás etc.) que um ResultSet “forward only” não permite.
No seu caso, é possível usar essa List<AlgumaCoisa> onde AlgumaCoisa é uma classe que só encapsula os campos de um registro dessa consulta?

Então, o processo de leitura do ResultSet para o Bean está demorado, então esse processo iria para a Thread, logo preciso de cópia da Thread antes de preencher o beans, senão pode acontecer como eu disse acima, pular registros e duplicar outros.

[quote=samuelm7]thingol, sim, a intenção é retornar muitos dados, mas o custo benefício do CachedRowSet, está muito baixo no meu caso pelo menos.

giulianocosta não posso passar o mesmo ResultSet, pois como as Threads não necessariamente rodam sequencialmente, poderiam ocasionar a perda de registros. Exemplo: uma thread da next() e para, ai vem outra e dá next, terei um registro duplicado e um será pulado.[/quote]

Nao nao Samuel. Uma thread(Flag) vai varrendo o resultset e colocando as linhas em memória(List, hash, sei la o que) de uma Queue. A outra vai lendo esses dados dessa Queue. Se a Consumidora for mais rápida ele paralisa e espera a fila aumentar para consumir de novo(Dai essa implementação vai de como é sua necessidade de performance vs hardware disponível).
Se tu tens multi-core ai vai se beneficiar dessa implementação. Eu já tive que fazer isso para uma leitora de ResultSet e uma “escrevedora” de arquivo texto que ia consumindo. Ficou bem rápido.

Olha a gambi que planejei:

Duas ou amis threads acessando os registros desse ResultSet onde cada acesso é intercalado com o acesso da outra thread.
Pra uma saber onde a outra parou ela acessa um “contador” de registro syncronized (pra garantir que elas nao consultaram e alteraram ao mesmo tempo) e o altera pra indicar que já fez a sua leitura.
Não sei se expliquei muito bem, foi uma idéia maluca que me ocorreu. Nem sei se funciona, mas se for da forma como estou pensando da pra instanciar N threads e elas se comportariam muito bem.
Ok, podem apedrejar =Z

Abraços e bom final de semana!

O problema que vejo nesta abordagem é que não há garantia de que o ResulSet seja thread-safe. O que já fiz e deu resultado foi o seguinte:

Uma thread principal faz selects, usando alguma condição adicional para particionar a query. Por exemplo, se sua query implica em trazer todas as vendas do mês, vc. pode reescreve-la limitando o período a um dia, hora, ou algo que faça sentido no seu domínio. Como todas as consultas ocorrem em cima das mesma tabelas, é bem provável que não haja ganho em adicionar threads neste estágio (estágio produtor). Após obter o resultset, o thread produtor coloca-o em uma fila e passa para o próximo select.

Para consumir estes resultsets, crie um pool de threads que tiram os resultsets da fila e fazem o processamento dos mesmos.

Em cenário real, esta abordagem permitiu um ganho de mais de 10x no tempo de processamento, mas evidentemente isto foi possível devido a uma série de fatores:

  • O banco de dados ficava em uma outra máquina
  • Testes iniciais mostraram que o servidor não apresentava degradação significativa de performance para trazer o primeiro resultado mesmo quando eram feitas várias consultas sobrepostas (com faixas diferentes)
  • Na fase de transferência de dados (iteração do resultset), o processamento de um resultset ocorria a uma taxa inferior à capacidade de tranferência de dados entre o banco e o servidor.

Essa solução acima me parece a mais inteligente e viável, pelo menos por enquanto.