2011-09-07 17 views
6

Sono un fan di ORM - Object Relational Mapping e l'ho usato con Rails da un anno e mezzo. In precedenza, utilizzo le query non elaborate con JDBC e faccio in modo che Database esegua il sollevamento pesante tramite Stored Procedures. Con ORM, inizialmente ero felice di fare cose come coach.manager e manager.coaches che erano molto semplici e facili da leggere.Svantaggi del mapping relazionale degli oggetti

Ma con il passare del tempo c'erano numerose associazioni che si avvicinavano e ho finito per fare a.b.c.d che sparavano domande in tutte le direzioni, dietro le quinte. Con le rotaie e il rubino, il netturbino è impazzito e ha impiegato pazzesco tempo per caricare una pagina molto complessa che comporta dati relativamente minori. Ho dovuto sostituire questo codice di stile ORM con una semplice procedura memorizzata e il risultato che ho visto era enorme. Una pagina che impiega 50 secondi per caricarsi ora richiede solo 2 secondi.

Con questa enorme differenza, dovrei continuare a utilizzare ORM? È molto chiaro che ha overheads severi rispetto a una query non elaborata.

In generale, quali sono le insidie ​​generali dell'utilizzo di un framework ORM come Hibernate, ActiveRecord?

+0

Stai utilizzando il recupero pigro? Fondamentalmente 'ORM' carica tanto quanto tu dici ... –

+0

@Petar Minichev: Beh, non posso dire una risposta diretta a questo poiché sto facendo tutti i tipi di riprese che l'ORM mi consente. C'è un po 'di compromesso ovunque – bragboy

risposta

5

Penso che tu abbia già identificato il compromesso principale associato al software ORM. Ogni volta che aggiungi un nuovo livello di astrazione che tenta di fornire un'implementazione generalizzata di qualcosa che hai usato a mano, ci sarà una perdita di prestazioni/efficienza.

Come annotato, attraversando molteplici relazioni, come a.b.c.d può essere inefficiente, perché la maggior parte del software ORM farà una query di database indipendente per ogni . lungo la strada. Ma non sono sicuro che questo significhi che dovresti eliminare del tutto l'ORM. La maggior parte delle soluzioni ORM (o almeno, certamente Hibernate) consente di specificare query personalizzate in cui è possibile ripristinare esattamente ciò che si desidera in un'unica operazione di database. Questo dovrebbe essere veloce quanto il tuo SQL dedicato.

In realtà il problema è di capire come lo strato ORM sta lavorando dietro le quinte, e rendersi conto che, mentre qualcosa come a.b.c.d è semplice da scrivere, ciò che fa sì che il livello ORM di fare come viene valutato non lo è. Come regola generale, passo sempre con l'approccio più semplice possibile per iniziare, quindi scrivo query ottimizzate in aree in cui ha senso/dove è ovvio che l'approccio semplice non si ridimensiona.

12

Un ORM è solo uno strumento. Se non lo usi correttamente, avrai cattivi risultati.

Nulla ti impedisce di utilizzare query HQL/criteri dedicate, con join o proiezioni di recupero, per restituire le informazioni che la tua pagina deve visualizzare nel minor numero possibile di query. Questo richiederà più o meno lo stesso tempo delle query SQL dedicate.

Ma ovviamente, se si ottiene tutto per ID e si naviga tra gli oggetti senza rendersi conto di quante query genera, ciò comporterà lunghi tempi di caricamento. La chiave è sapere esattamente cosa fa l'ORM dietro la scena e decidere se è appropriato o se deve essere adottata un'altra strategia.

3

Direi che uno dovrebbe utilizzare lo strumento appropriato per diversi compiti.

Ad esempio, per le operazioni CRUD, i framework ORM come Hibernate possono accelerare lo sviluppo e funzioneranno abbastanza bene. A volte è necessario apportare alcune modifiche necessarie per ottenere prestazioni accettabili. Non sono sicuro, il tuo compito (quello che è durato 50 secondi con Hibernate) non è stato possibile farlo correttamente con Hibernate, perché non ci hai fornito i dettagli.

D'altro canto, ad esempio, le operazioni di massa che coinvolgono centinaia di migliaia di record non sono il tipo di attività che ci si aspetterebbe da Hibernate senza una significativa penalizzazione delle prestazioni.

1

Sono con Petar dai vostri commenti riguardo alla raccolta pigra. Supponiamo che tu abbia una tabella html riempita di campi dall'oggetto a.b.c.d. Potresti trovare il tuo framework che fa girare il database migliaia di volte (forse molte di più). Lo svantaggio di ORM in questo caso è che devi leggere attentamente la documentazione. La maggior parte dei framework supporta la disattivazione dell'accesso pigro e molti addirittura supportano l'aggiunta della propria logica di elaborazione per associare il set di dati.

Il netto è che quasi tutti gli ORM sono quasi sicuramente migliori di qualsiasi cosa tu abbia intenzione di scrivere da solo. Ti troverai addossato al mantenimento di enormi librerie di piastre o peggio ancora scrivendo lo stesso codice più e più volte.

2

Come già accennato, ORM è solo uno strumento e si può usare eiter buono o cattivo.

Uno dei problemi di prestazioni più tipici in ORM è il problema delle query 1 + N. È causato dal caricamento di oggetti aggiuntivi per ciascuno degli oggetti dall'elenco. Ciò è causato dal recupero fasullo di entità 1-to-n-relazione per ogni elemento della lista, la negoziazione sta usando le query HQL, specificando i campi in proiezione o contrassegnando il recupero delle relazioni da 1 a n in pigro.

In qualsiasi momento, è necessario sapere esattamente cosa sta facendo l'ORM per ottenere buone prestazioni. Non capire quali operazioni vengano eseguite in background è un modo di fare il disastro (codice lento, buggato e difficile da analizzare a causa di inutili e scorrette soluzioni).

0

Attualmente stiamo esaminando di passare dal nostro livello di archivio dati con separazione netta di oggetti di trasferimento e oggetti di accesso ai dati a JPA. Abbiamo utilizzato un generatore per creare TO, DAO e SQL DDL nonché da alcuni documenti in formato docbook. Con ciò tutta la nostra roba dalla documentazione, la struttura del database e le classi Java generate dove sempre in sincronia con una buona documentazione del database stesso.

Quello che abbiamo scoperto finora utilizzando JPA:

  1. riferimenti chiave stranieri non possono essere utilizzati per le importazioni, alcuni speciali query e così via, perché non deve essere collocato in un gestita entità. JPA consente solo la classe di destinazione lì.
  2. L'accesso a un ambito di sessione utente è difficile fino a impossibile. Noi non abbiamo ancora idea di come ottenere l'ID utente nella colonna "userWhoLastMadeAnUpdate" in un metodo PrePersist.
  3. Qualcosa dovrebbe essere abbastanza facile con un ORM, vale a dire "classe mappatura" non funziona affatto. Utilizziamo HalDateTime (http://sourceforge.net/projects/haldatetime/) internamente. Soprattutto nel client. La mappatura diretta con JPA non è possibile sebbene HalDateTime lo supporti. A causa delle restrizioni JPA , dobbiamo utilizzare due campi nell'entità.
  4. JPA utilizza un solo file XML per descrivere la mappatura. Quindi devi leggere almeno in due file per capire la relazione tra la classe Java e il database. E il file XML diventa enorme per le applicazioni di grandi dimensioni.
  5. In alternativa, gli ORM forniscono annotazioni nella classe Java stessa. Quindi è più facile da imparare e capire la relazione.Ma impone allo di vedere tutto quel materiale di database nel livello client (che interrompe completamente un layering appropriato).
  6. Dovrai limitarti a rimanere il più vicino possibile ad una struttura di database pulita come possibile. Altrimenti, di sicuro finirà con un casino di domande e dichiarazioni da parte dell'ORM.
  7. Utilizzare un ORM che fornisce un linguaggio di query che è simile a SQL stesso (JPA sembra abbastanza accettabile qui). Un linguaggio indotto dall'ORM rende molto costoso il supporto di un'applicazione di grandi dimensioni.
Problemi correlati