Domanda

Sto eseguendo una query su una tabella in un database postgresql. Il database si trova su un computer remoto. La tabella ha circa 30 sotto-tabelle che utilizzano postgresql capacità di partizionamento .

La query restituirà un set di risultati di grandi dimensioni, circa 1,8 milioni di righe.

Nel mio codice utilizzo il supporto jdbc di primavera, metodo JdbcTemplate.query , ma il mio RowCallbackHandler non viene chiamato.

La mia ipotesi migliore è che il driver jdbc postgresql (utilizzo la versione 8.3-603.jdbc4) sta accumulando il risultato in memoria prima di chiamare il mio codice. Ho pensato che configurazione fetchSize potrebbe controllarlo, ma l'ho provato e non cambia nulla. L'ho fatto come manuale di postgresql consigliato .

Questa query ha funzionato bene quando ho usato Oracle XE. Ma sto provando a migrare su postgresql a causa della funzione di partizionamento, che non è disponibile in Oracle XE.

Il mio ambiente:

  • Postgresql 8.3
  • Windows Server 2008 Enterprise 64-bit
  • JRE 1.6 64-bit
  • Primavera 2.5.6
  • Driver JDBC Postgresql 8.3-603
È stato utile?

Soluzione

Per utilizzare un cursore per recuperare i dati è necessario impostare il tipo ResultSet di ResultSet.TYPE_FORWARD_ONLY (impostazione predefinita) e autocommit su false oltre a impostare una dimensione di recupero. Questo è indicato nel documento a cui ti sei collegato ma non hai esplicitamente menzionato di aver fatto questi passaggi.

Prestare attenzione allo schema di partizionamento di PostgreSQL. Fa davvero cose orribili con l'ottimizzatore e può causare enormi problemi di prestazioni dove non dovrebbero esserci (a seconda delle specifiche dei dati). In ogni caso, la tua riga è solo 1,8 milioni di righe? Non vi è alcun motivo per cui dovrebbe essere partizionato in base alla sola dimensione dato che è opportunamente indicizzato.

Altri suggerimenti

Scommetto che non esiste un singolo client della tua app che abbia bisogno di 1,8 milioni di righe contemporaneamente. Dovresti pensare a un modo sensato per dividere i risultati in pezzi più piccoli e dare agli utenti la possibilità di iterarli.

Questo è ciò che fa Google. Quando fai una ricerca potrebbero esserci milioni di hit, ma restituiscono 25 pagine alla volta con l'idea che troverai quello che vuoi nella prima pagina.

Se non è un client e i risultati vengono in qualche modo massaggiati, ti consiglio di lasciare che il database scricchioli tutte quelle righe e semplicemente restituisca il risultato. Non ha senso restituire 1,8 milioni di righe solo per fare un calcolo sul livello intermedio.

Se nessuno dei due si applica, hai un vero problema. È ora di ripensarci.

Dopo aver letto le risposte successive, mi sembra che questa sia più una soluzione di reporting che dovrebbe essere analizzata in batch o calcolata in tempo reale e archiviata in tabelle che non fanno parte del sistema transazionale. Non è possibile ridimensionare portando 1,8 milioni di righe al livello intermedio per il calcolo delle medie mobili.

Ti consiglio di riorientare te stesso - inizia a pensarci come una soluzione di segnalazione.

La proprietà fetchSize ha funzionato come descritto nel postgres manual .

Il mio errore è stato quello di impostare auto commit = false su una connessione da un pool di connessioni che non era la connessione utilizzata dall'istruzione preparata.

Grazie per tutto il feedback.

Ho fatto tutto quanto sopra, ma avevo bisogno di un ultimo pezzo: assicurati che la chiamata sia inclusa in una transazione e imposta la transazione in sola lettura, in modo che non sia richiesto lo stato di rollback.

Ho aggiunto questo: @Transactional (readOnly = true)

Saluti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top