Pergunta

Estou executando uma consulta em uma tabela em um banco de dados PostgreSQL. O banco de dados está em uma máquina remota. A tabela tem cerca de 30 sub-tabelas usando PostgreSQL particionamento capacidade .

A consulta retornará um conjunto de resultados grande, algo em torno de 1,8 milhões de linhas.

No meu código eu uso apoio primavera jdbc, método JdbcTemplate.query , mas meu RowCallbackHandler não está sendo chamado.

Meu melhor palpite é que o driver JDBC do PostgreSQL (eu uso a versão 8.3-603.jdbc4) está acumulando o resultado na memória antes de chamar o meu código. Eu pensei que o FetchSize configuração poderia controlar isso, mas eu tentei e nada muda. Eu fiz isso como o manual PostgreSQL recomended .

Esta consulta funcionou bem quando eu usei o Oracle XE. Mas eu estou tentando migrar para o PostgreSQL por causa do recurso de particionamento, que não está disponível no Oracle XE.

O meu ambiente:

  • PostgreSQL 8.3
  • Windows Server 2008 Enterprise de 64 bits
  • JRE 1.6 64 bits
  • Spring 2.5.6
  • PostgreSQL JDBC driver 8,3-603
Foi útil?

Solução

Para usar um cursor para recuperar os dados que você tem que definir o tipo ResultSet de ResultSet.TYPE_FORWARD_ONLY (o padrão) e autocommit para false além de definir um tamanho de busca. Que é referenciado no doc é ligada ao mas você não mencionou explicitamente que você fez esses passos.

Tenha cuidado com o esquema de particionamento do PostgreSQL. Ele realmente faz coisas muito horríveis com o otimizador e pode causar problemas enormes de desempenho onde não deveria ser (dependendo especificidades de seus dados). Em qualquer caso, é a sua linha apenas 1.8M linhas? Não há nenhuma razão que ele teria que ser dividido com base no tamanho sozinho, dado que está devidamente indexado.

Outras dicas

Eu estou apostando que não há um único cliente do seu aplicativo que precisa de 1.8M linhas, tudo ao mesmo tempo. Você deve pensar de uma maneira sensata para pedaço os resultados em pedaços menores e dar aos usuários a chance de iterate através deles.

Isso é o que o Google faz. Quando você faz uma busca que pode haver milhões de acessos, mas eles retornam 25 páginas de cada vez com a idéia de que você vai encontrar o que deseja na primeira página.

Se não é um cliente, e os resultados estão sendo massageado, de alguma forma, eu recomendo deixar a crise de banco de dados de todas as linhas e simplesmente retornar o resultado. Não faz sentido para retornar 1.8M linhas apenas para fazer um cálculo na camada intermediária.

Se nenhum desses aplicar, você tem um problema real. Hora de repensar isso.

Depois de ler as respostas posteriores que soa para mim como esta é mais uma solução de relatórios que devem ser triturado em lote ou calculados em tempo real e armazenadas em tabelas que não fazem parte do seu sistema transacional. Não há nenhuma maneira que trazer linhas 1.8M para a camada intermediária para o cálculo de médias móveis podem ser dimensionados.

Eu recomendo reorientar-se - começar a pensar nisso como uma solução de relatórios.

A propriedade FetchSize trabalhou como descrito em postgres Manual .

O meu erro foi que eu estava assentado auto commit = false para uma conexão de um pool de conexão que não era a conexão que está sendo usada pela declaração preparada.

Obrigado por todo o feedback.

Eu fiz tudo acima, mas eu precisava de uma última parte:. Certifique-se a chamada é envolto em uma transação e definir a transação só para ler, para que nenhum estado de reversão é necessária

Eu adicionei o seguinte: @Transactional(readOnly = true)

Saúde.

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