ResultSet: recupero dei valori delle colonne per indice rispetto al recupero per etichetta

Quando si utilizza JDBC, mi capita spesso di trovare costrutti come

ResultSet rs = ps.executeQuery(); while (rs.next()) { int id = rs.getInt(1); // Some other actions } 

Mi sono chiesto (e anche agli autori di codice) perché non usare le etichette per recuperare i valori delle colonne:

 int id = rs.getInt("CUSTOMER_ID"); 

La migliore spiegazione che ho sentito è qualcosa riguardante le prestazioni. Ma in realtà, rende l’elaborazione estremamente veloce? Non ci credo, anche se non ho mai eseguito misurazioni. Anche se il recupero per etichetta sarebbe un po ‘più lento, tuttavia, a mio parere fornisce una migliore leggibilità e flessibilità.
Quindi qualcuno potrebbe darmi una buona spiegazione per evitare di recuperare i valori delle colonne per indice di colonna invece di etichetta di colonna? Quali sono i pro ei contro di entrambi gli approcci (forse, riguardo certi DBMS)?

È necessario utilizzare le etichette stringa per impostazione predefinita.

Professionisti:

  • Indipendenza dell’ordine delle colonne
  • Migliore leggibilità / manutenibilità

Contro:

  • Non hai alcun controllo sui nomi delle colonne (accesso tramite stored procedure)

Quale preferiresti?

int?

int i = 1;
customerId = resultSet.getInt (i ++);
customerName = resultSet.getString (i ++);
customerAddress = resultSet.getString (i ++);

o stringhe?

customerId = resultSet.getInt (“customer_id”);
customerName = resultSet.getString (“customer_name”);
customerAddress = resultSet.getString (“customer_address”);

E se ci fosse una nuova colonna inserita nella posizione 1? Quale codice preferiresti? Oppure se l’ordine delle colonne è cambiato, quale versione di codice dovresti cambiare?

Ecco perché è necessario utilizzare le etichette stringa per impostazione predefinita.

Avvertenza: qui prenderò il sopravvento, perché questo mi fa impazzire.

Il 99% * del tempo, è una micro-ottimizzazione ridicola che le persone hanno una vaga idea che rende le cose ‘migliori’. Questo ignora completamente il fatto che, a meno che non siate in un ciclo estremamente stretto e impegnato su milioni di risultati SQL per tutto il tempo , che si spera siano rari, non lo noterete mai. Per tutti coloro che non lo fanno, il costo dello sviluppatore per il mantenimento, l’aggiornamento e la correzione dei bug nell’indicizzazione delle colonne è molto maggiore del costo incrementale dell’hardware per l’applicazione infinitamente peggiore.

Non codificare ottimizzazioni come questa. Codice per la persona che lo mantiene. Quindi osserva, misura, analizza e ottimizza. Osservare di nuovo, misurare di nuovo, analizzare di nuovo e ottimizzare di nuovo.

L’ottimizzazione è praticamente l’ultimo passo nello sviluppo, non il primo.

* La figura è composta.

La risposta è stata accettata, in ogni caso, ecco alcune informazioni aggiuntive ed esperienze personali che non ho ancora visto proporre.

Usa i nomi delle colonne (le costanti e non i letterali sono preferiti) in generale e se ansible. Questo è sia più chiaro, è più facile da mantenere, e le modifiche future hanno meno probabilità di infrangere il codice.

C’è, tuttavia, un uso per gli indici di colonne. In alcuni casi, questi sono più veloci, ma non sufficientemente da escludere le ragioni sopra indicate per i nomi *. Questi sono molto utili quando si sviluppano strumenti e metodi generali che si occupano di ResultSet . Infine, potrebbe essere necessario un indice perché la colonna non ha un nome (come un aggregato senza nome) o ci sono nomi duplicati quindi non esiste un modo semplice per fare riferimento a entrambi.

* Nota che ho scritto alcuni driver JDBC e ho guardato all’interno di alcuni open source uno e internamente questi usano gli indici delle colonne per fare riferimento alle colonne dei risultati. In tutti i casi con cui ho lavorato, il driver interno mappa innanzitutto il nome di una colonna in un indice. Pertanto, puoi facilmente vedere che il nome della colonna, in tutti questi casi, richiederebbe sempre più tempo. Questo potrebbe non essere vero per tutti i driver però.

Dalla documentazione java:

L’interfaccia ResultSet fornisce i metodi getter (getBoolean, getLong e così via) per il recupero dei valori delle colonne dalla riga corrente. I valori possono essere recuperati utilizzando il numero di indice della colonna o il nome della colonna. In generale, l’uso dell’indice di colonna sarà più efficiente. Le colonne sono numerate da 1. Per la massima portabilità, le colonne dei set di risultati all’interno di ciascuna riga devono essere lette nell’ordine da sinistra a destra e ogni colonna deve essere letta una sola volta.

Ovviamente ogni metodo (denominato o indicizzato) ha il suo posto. Sono d’accordo che le colonne nominate dovrebbero essere quelle predefinite. Tuttavia, nei casi in cui è richiesto un numero enorme di cicli e dove l’istruzione SELECT è definita e mantenuta nella stessa sezione di codice (o class), gli indici dovrebbero essere ok – è consigliabile elencare le colonne selezionate, non solo “SELEZIONA * DA …”, poiché qualsiasi modifica della tabella interromperà il codice.

Certo, l’uso dei nomi delle colonne aumenta la leggibilità e semplifica la manutenzione. Ma usare i nomi delle colonne ha un rovescio della medaglia. Come sapete, SQL consente più nomi di colonne con lo stesso nome, non vi è alcuna garanzia che il nome della colonna che avete digitato nel metodo getter di resultSet punti effettivamente al nome della colonna a cui intendete accedere. In teoria, l’uso dei numeri indice invece dei nomi delle colonne viene prefferito, ma riduce la leggibilità …

Grazie

Non credo che usare le etichette influenzi le prestazioni di molto. Ma c’è un altro motivo per non usare String s. O int , per quella questione.

Prendi in considerazione l’uso delle costanti. L’utilizzo di una costante int rende il codice più leggibile, ma anche meno probabile che presenti errori.

Oltre a essere più leggibile, la costante impedisce anche di inserire errori di battitura nei nomi delle etichette – il compilatore genererà un errore se lo fai. E qualsiasi IDE che valga qualcosa, lo raccoglierà. Questo non è il caso se usi String o ints .

Ho eseguito alcune analisi delle prestazioni su questo argomento esatto su un database Oracle. Nel nostro codice abbiamo un ResultSet con numerose colonne e un numero enorme di righe. Dei 20 secondi (!) Richiesti per eseguire il metodo oracle.jdbc.driver.ScrollableResultSet.findColumn (nome String) richiede circa 4 secondi.

Ovviamente c’è qualcosa di sbagliato nella progettazione generale, ma l’utilizzo di indici al posto dei nomi delle colonne probabilmente richiederebbe questo tempo di 4 secondi.

Puoi avere il meglio di entrambi! La velocità di utilizzo degli indici con la manutenibilità e la sicurezza dell’utilizzo dei nomi delle colonne.

Innanzitutto – a meno che tu non stia eseguendo il ciclo con un set di risultati, usa solo i nomi delle colonne.

  1. Definisci un insieme di variabili intere, una per ogni colonna a cui accedi. I nomi delle variabili possono includere il nome della colonna: ad es. ILast_Name.

  2. Prima del ciclo di set di risultati iterare attraverso i metadati della colonna e impostare il valore di ogni variabile intera sull’indice della colonna del nome della colonna corrispondente. Se l’indice della colonna ‘Last_Name’ è 3, imposta il valore di ‘iLast_Name’ su 3.

  3. Nel ciclo del set di risultati utilizzare i nomi delle variabili intere nei metodi GET / SET. Il nome della variabile è un indizio visivo per lo sviluppatore / manutentore sul nome effettivo della colonna a cui si accede ma il valore è l’indice della colonna e darà le migliori prestazioni.

NOTA: la mapping iniziale (ovvero il nome della colonna nella mapping dell’indice) viene eseguita una sola volta prima del ciclo piuttosto che per ogni record e colonna del ciclo.

Il driver JDBC si preoccupa che la colonna indicizzi la ricerca. Quindi, se estrai i valori per nome di colonna ogni volta che il driver effettua una ricerca (di solito in una mappa hash) per verificare l’indice corrispondente per il nome della colonna.

Sono d’accordo con le risposte precedenti che la performance non è qualcosa che può costringerci a selezionare uno dei due approcci. Sarebbe bene considerare invece le seguenti cose:

  • Leggibilità del codice: per ogni sviluppatore che legge le etichette del codice ha molto più senso degli indici.
  • Manutenzione: pensa alla query SQL e al modo in cui viene gestita. Cosa è più probabile che accada nel tuo caso dopo aver risolto / migliorato / rifatto la query SQL: cambiando l’ordine delle colonne estratte o cambiando i nomi delle colonne dei risultati. Mi sembra che cambiare l’ordine delle colonne estratte (come risultato dell’aggiunta / eliminazione di nuove colonne nel set di risultati) abbia maggiori probabilità di accadere.
  • Incapsulamento: nonostante si scelga, provare ad isolare il codice in cui si esegue la query SQL e analizzare il set di risultati nello stesso componente e rendere solo questo componente consapevole dei nomi delle colonne e del loro mapping agli indici (se si è deciso di utilizzarli ).

Usare l’indice è un tentativo di ottimizzazione.

Il tempo risparmiato da questo è sprecato dallo sforzo extra necessario allo sviluppatore per cercare i dati necessari per verificare se il loro codice funzionerà correttamente dopo le modifiche.

Penso che sia il nostro istinto incorporato a usare numeri invece di testo.

Oltre alla ricerca di etichette per le etichette, si ottiene anche una creazione extra di stringhe. Anche se accadrà sullo stack ma continua a farlo con un costo.

Dipende tutto dalla scelta individuale e fino alla data ho usato solo indici 🙂