Applicazione Java - Come ottimizzare le chiamate al database e lo spazio e il tempo che è più importante?

2

Sto scrivendo una semplice app Java da eseguire settimanalmente. L'app necessita di un database delle chiamate per ottenere dati, controllarli e aggiornarli.

Il flusso di cui ho bisogno è il seguente:

  • %codice%
    • select configure,orgID where status=true from orgs; ha migliaia di righe, orgs è blob
  • Controlla l'oggetto blob configure e filtrato l'elenco configure
  • per l'elenco orgID filtrato, orgID
    • select * from users where status=true and orgID in (orglist) è una tabella enorme. per ogni users , ci possono essere fino a 400k utenti.
  • per le informazioni degli utenti, aggiorniamo una colonna di tutti questi utenti

Ho due domande:

  1. quando selezioniamo orgID questo campo è blob e può essere grande quanto 1k. È buona pratica ottenere migliaia di file contemporaneamente? o è meglio effettuare più chiamate db? tempo e spazio, che è più importante?

  2. la tabella utenti ha milioni di righe, è necessario aggiornare forse 1 colonna per 1 milione di righe. qual è una buona pratica per fare questo aggiornamento? è meglio fare 1 milione di chiamate db? o con meno db chiamate possibili?

posta c2340878 03.11.2016 - 08:42
fonte

3 risposte

1
  1. when we select configure this field is blob and it can be as large as 1k. Is it good practice to get thousands of rows at one time? or it is better to make multiple db call? time and space, which is more important?

Questo dipende totalmente dall'applicazione. La domanda è: soddisfa i tuoi requisiti di rendimento?

Per una semplice app che viene eseguita una volta alla settimana, l'uso del tempo e della memoria non è probabilmente molto importante. Vorrei scrivere la versione semplice (ottenere tutto in una volta in una singola query) prima. Finché funziona bene, non me ne preoccuperei. E 1K volte diverse migliaia probabilmente non causerà un problema.

Se riscontri problemi di prestazioni, solo allora dovresti preoccuparti di modificarlo per utilizzare più chiamate DB.

  1. users table has millions rows, we need update perhaps 1 column for 1 million rows. what is a good practice to make this update? is it better to make 1 million db call? or as little db calls as possible?

Come sopra, i tuoi requisiti di rendimento dovrebbero guidare tali decisioni. Ma in questo caso, fare milioni di chiamate DB è più probabile che sia problematico. Inoltre, un singolo aggiornamento che modifica molte righe contemporaneamente è in genere facile da scrivere.

Quindi, punterei a una singola dichiarazione di aggiornamento che aggiorni tutto, o al massimo una dichiarazione di aggiornamento per orgID .

    
risposta data 03.11.2016 - 09:23
fonte
0

C'è probabilmente una parte della micro-ottimizzazione preventiva qui, ma penso di poter indirizzare alcuni punti generali qui.

Prepara test realistici

Tuttavia c'è molto che puoi fare, iniziamo dall'inizio

  1. Poiché si tratta di un'operazione settimanale, non è necessario eseguirla istantaneamente. Definisci una finestra realistica di esecuzione del tempo
  2. Crea dati di test realistici (o se puoi avere quelli veri è ancora meglio)
  3. Benchmark.
  4. Puoi provare a cambiare la dimensione dei tuoi dati di test per avere una stima molto approssimativa della complessità temporale.

Memoria insufficiente

Considerando la dimensione dei tuoi dati e il tuo blob probabilmente avrai degli errori di memoria. Questo punto è stato risolto in StackOverflow

Se si utilizza un ORM o EntityManager da JPA, è possibile considerare di cambiare per un'operazione JDBC non elaborata. Altrimenti non dimenticare di svuotare la cache utilizzando il metodo flush .

Chiamate al database

Più chiamate di rete possono facilmente diventare un collo di bottiglia. Un join completo può anche costare molto al database. Invece di recuperare ogni utente utilizzando orgID in (orglist) , puoi scegliere di eseguire una query per orgID . A meno che tu non abbia 10000 di organi diversi, il costo di questo non sarà nulla. Certo, devi essere sicuro che la tua quantità di memoria seguirà.

Multithreading

Considera questo solo se i seguenti requisiti sono tutti mets:

  • L'elaborazione dei dati in Java per calcolare i risultati richiede una quantità di tempo misurabile nell'intero processo.
  • Non è necessario che tutto ciò avvenga in un'unica transazione.
  • Puoi dividere il tuo processo per assicurarti che ogni riga non sia bloccata da più thread (ad esempio 1/10 orgID per thread). Assicurati che il tuo database applichi correttamente il blocco a livello di riga, a meno che tu non abbia a che fare con un ambiente legacy questo punto dovrebbe andare bene. **
  • A meno che alcune micro ottimizzazioni siano davvero brutte in termini di manutenzione, ... sei praticamente senza opzioni.

Preparati per il futuro

Se le finestre temporali sono qualcosa come 5h max e il tuo database dovrebbe crescere e vivere per 10 anni, puoi scegliere tra:

  1. Assicurati che abbia buone possibilità di funzionare correttamente anche in 10 anni stimando il volume previsto di dati.
  2. Stima quando (o più probabilmente, a quale volume di dati) questo pezzo di codice avrà bisogno di rielaborazione o aumenterà il tempo di Windows.

Benchmarks

Sì, l'ho già detto, ma per essere sicuro che non lo dimenticherete, è probabile che ogni modifica per migliorare le prestazioni aumenti la complessità del codice.

Convalidare con un benchmark ogni modifica di progetto / codice che ciò che hai fatto abbia avuto un impatto reale.

    
risposta data 03.11.2016 - 12:06
fonte
0

when we select configure this field is blob and it can be as large as 1k. Is it good practice to get thousands of rows at one time?

Ci sono alcuni livelli in questo. Quando selezioni un grande insieme di righe dal DB, non ti invia un enorme ammasso di byte. Quello che succede è che c'è un cursore sul DB con una dimensione che puoi configurare. Quindi se la dimensione del tuo cursore è di 1000 righe, non prenderà tutte le righe contemporaneamente. Generalmente non dovrai preoccuparti di questo tranne per le cose che citerò più avanti in questa risposta.

Tuttavia, l'altro aspetto di ciò che fai con le righe. Se li inserisci tutti in un elenco sulla tua applicazione (che è ciò che le persone fanno con gli ORM) avrai bisogno di allocare spazio per tutti questi record. Odio questo approccio. È la causa più comune di programmi Java gonfiati. Dovresti davvero eseguire il looping dei record dalla connessione al database come iteratore.

or it is better to make multiple db call?

Ciò dipende dalle considerazioni sulla concorrenza descritte di seguito.

time and space, which is more important?

L'analisi del trade-off del tempo-spazio è qualcosa che si applica quando hai complessità algoritmica. Questo non sembra uno di quei casi. Se tutto quello che stai facendo è leggere una singola riga e scrivere un aggiornamento, usare più memoria non accelera le cose. In effetti, probabilmente rallenterà il tuo programma. Ci vuole tempo per allocare e gestire la memoria. Cerchi di non allocare più memoria del necessario per eseguire l'attività successiva.

users table has millions rows, we need update perhaps 1 column for 1 million rows. what is a good practice to make this update? is it better to make 1 million db call? or as little db calls as possible?

Suppongo qui che sia necessario esaminare ogni riga e fare un aggiornamento che non può essere fatto semplicemente in un'istruzione SQL one-shot. Non c'è una risposta semplice a questa domanda e questo dipende dal fatto che ci saranno altre applicazioni che interagiscono con queste tabelle mentre stai facendo questo.

Se stai facendo 'select for update', probabilmente non vuoi farlo in un grosso commit. Il motivo per cui lo utilizzi è impedire ad altre applicazioni di modificare i dati tra la selezione e l'aggiornamento. In altre parole, bloccherai tutti questi record per la durata.

Anche se non sei preoccupato per la concorrenza o le letture sporche, probabilmente non vuoi modificare un milione di record e poi impegnarti alla fine perché:

  1. Se c'è un problema in qualsiasi momento in questo processo, anche se minore, devi ricominciare dall'inizio.
  2. Scrivere una tonnellata di modifiche non vincolanti in un DB mette un sacco di stress sulle sue risorse.

Quindi c'è un punto debole per le prestazioni per i commit. Tu commetti ognuno e ci sarà un piccolo sovraccarico. Potresti impegnarli in lotti, ma i tuoi tentativi sono un po 'più complicati. Personalmente, a meno che tu non sappia che esiste un problema di prestazioni, probabilmente eseguirò immediatamente ogni cambiamento. È il più facile da ottenere. Un milione di dischi non è poi così tanto al giorno. E 1K non è molti dati. Oracle (ad esempio) non si preoccupa nemmeno di mettere 1K fuori tabella a meno che tu non lo dica.

    
risposta data 02.02.2017 - 04:20
fonte

Leggi altre domande sui tag