Usi un ORM o un semplice SQL? [chiuso]


247

Per alcune delle app che ho sviluppato (poi ho continuato a dimenticare), ho scritto SQL semplice, principalmente per MySQL. Anche se ho usato ORM in Python come SQLAlchemy , non mi sono attaccato a lungo. Di solito era la documentazione o la complessità (dal mio punto di vista) a trattenermi.

Lo vedo così: uso un ORM per la portabilità, semplice SQL se sta per usare un solo tipo di database. Sto davvero cercando consigli su quando utilizzare un ORM o SQL quando si sviluppa un'app che necessita del supporto del database.

Pensandoci, sarebbe molto meglio usare solo un wrapper leggero per gestire le incoerenze del database rispetto all'utilizzo di un ORM.


Standardizzazione, sicurezza, manutenibilità, astrazione linguistica, ASCIUTTO, ecc.
Ben

Le prestazioni con ORM possono essere vicine a SQL, dipende se la usi correttamente e con le impostazioni corrette ... Vedi ho per rendere EF6.x 5 volte più veloce: linkedin.com/pulse/…
baHI

Per l'architettura ORM e come fare (cosa evitare), ecco il mio altro link: linkedin.com/pulse/…
baHI

La mappatura relazionale a oggetti (ORM) è già molto popolare in molti linguaggi di programmazione e una delle migliori alternative per SQL. Mi sono ispirato allo stile del concatenamento di metodi per creare CQL per il mio progetto TRIADB. healis.eu/triadb/#latest-release
Athanassios,

3
È stupido che questa domanda sia stata chiusa.
Mitch Wheat,

Risposte:


169

Gli ORM hanno alcune caratteristiche interessanti. Sono in grado di gestire gran parte del lavoro svolto dalla copia di colonne di database in campi oggetto. Di solito gestiscono la conversione dei tipi di data e ora della lingua nel tipo di database appropriato. Generalmente gestiscono le relazioni uno-a-molti in modo abbastanza elegante anche istanziando oggetti nidificati. Ho scoperto che se si progetta il proprio database tenendo presente i punti di forza e di debolezza dell'ORM, si risparmia molto lavoro nell'ottenere i dati dentro e fuori dal database. (Ti consigliamo di sapere come gestisce il polimorfismo e le relazioni molti-a-molti se hai bisogno di mapparli. Sono questi due domini che forniscono la maggior parte della "discrepanza di impedenza" che rende alcuni ORM il "vietnam dell'informatica" .)

Per le applicazioni che sono transazionali, vale a dire che si effettua una richiesta, si ottengono alcuni oggetti, si attraversano per ottenere alcuni dati e renderli su una pagina Web, la tassa sulle prestazioni è piccola e in molti casi ORM può essere più veloce perché memorizzerà nella cache gli oggetti visto prima, che altrimenti avrebbe interrogato il database più volte.

Per le applicazioni che richiedono molti report o che gestiscono un numero elevato di righe di database per richiesta, la tassa ORM è molto più pesante e la memorizzazione nella cache che si trasforma si trasforma in un grande e inutile onere di memorizzazione della memoria. In tal caso, la mappatura SQL semplice (LinQ o iBatis) o le query SQL codificate a mano in un DAL sottile è la strada da percorrere.

Ho trovato per qualsiasi applicazione su larga scala ti troverai ad usare entrambi gli approcci. (ORM per CRUD semplice e SQL / thin DAL per i report).


Potresti definire "un gran numero di righe del database per richiesta"? Per favore :)
Mosselman,

Quindi posso integrare JPA con IBatis per esempio ?? E farli funzionare nella stessa transazione?
Jaime Hablutzel,

2
Un'altra considerazione che nessuno sembra discutere è la gestione di base dello stato. L'intero stack di framework (JSF, JPA, ecc.) Si basa sui metodi get / set di bean Java. Questa è una tonnellata di boilerplate per ogni tavolo, per ogni colonna e ... ecco il vero anti-pattern: solo per esporre ogni campo come se fosse pubblico. In effetti, avere un metodo get / set su campi in un oggetto / tabella / riga è molto vicino alla violazione di ogni tenant di occultamento e incapsulamento delle informazioni. Infine, tornando alla gestione dello stato ... dov'è l'opzione di immutabilità? Possono o devono essere consentiti oggetti a mezzo set? Nessuna opzione con la maggior parte.
Darrell Teague,

2
Mi piacerebbe affinare e in particolare concordare una dichiarazione chiave in questa risposta. "Per le applicazioni che gestiscono un numero elevato di righe di database per richiesta, la tassa ORM è molto più pesante". ORM è buono solo per gli sviluppatori e la manutenzione perché la maggior parte degli sviluppatori non è molto brava con SQL, ma se in realtà si tratta di prestazioni, SQL ha la meglio.
Manachi,

"la maggior parte degli sviluppatori non è molto brava con SQL" ??? Direi che la maggior parte degli sviluppatori non sa come utilizzare correttamente LINQ, la potenza degli alberi delle espressioni e gli ORM in generale, la generazione di codice e molte altre cose. Ma no, non ho alcuna base per fare una dichiarazione così forte.
Adanay Martín,

253

Parlando come qualcuno che ha trascorso un bel po 'di tempo a lavorare con JPA (Java Persistence API, fondamentalmente l'API ORM standardizzata per Java / J2EE / EJB), che include Hibernate, EclipseLink, Toplink, OpenJPA e altri, condividerò alcuni dei miei osservazioni.

  1. Gli ORM non sono veloci. Possono essere adeguati e il più delle volte adeguati sono OK, ma in un ambiente ad alto volume a bassa latenza sono un no-no;
  2. In linguaggi di programmazione generici come Java e C # hai bisogno di un sacco di magia per farli funzionare (ad es. Tessitura a tempo di caricamento in Java, strumentazione, ecc.);
  3. Quando si utilizza un ORM, piuttosto che allontanarsi da SQL (che sembra essere l'intento), rimarrete stupiti da quanto tempo impiegate a modificare XML e / o annotazioni / attributi per far sì che il vostro ORM generi SQL performante;
  4. Per query complesse, non c'è davvero alcun sostituto. Come in JPA ci sono alcune query che semplicemente non sono possibili che sono in SQL raw e quando devi usare SQL grezzo in JPA non è carino (C # /. Net almeno ha tipi dinamici - var - che è molto più bello di un array di oggetti);
  5. Ci sono moltissimi "gotchas" quando si usano gli ORM. Ciò include un comportamento involontario o imprevisto, il fatto che è necessario integrare la capacità di eseguire aggiornamenti SQL sul database (utilizzando refresh () in JPA o metodi simili perché JPA per impostazione predefinita memorizza nella cache tutto in modo da non catturare un database diretto aggiornamento - l'esecuzione di aggiornamenti SQL diretti è un'attività di supporto alla produzione comune);
  6. La mancata corrispondenza relazionale agli oggetti causerà sempre problemi. Con tale problema c'è un compromesso tra complessità e completezza dell'astrazione. A volte ho sentito che l'APP è andato troppo oltre e ha colpito una vera legge di rendimenti decrescenti in cui il colpo di complessità non era giustificato dall'astrazione.

C'è un altro problema che richiede un po 'più di spiegazione.

Il modello tradizionale per un'applicazione Web è avere un livello di persistenza e un livello di presentazione (possibilmente con un servizio o altri livelli nel mezzo ma questi sono i due importanti per questa discussione). Gli ORM impongono una vista rigida dal livello di persistenza fino al livello di presentazione (ovvero le entità).

Una delle critiche a metodi SQL più grezzi è che si finisce con tutti questi VO (oggetti valore) o DTO (oggetti trasferimento dati) che vengono utilizzati da una sola query. Questo è pubblicizzato come un vantaggio degli ORM perché te ne sbarazzi.

La cosa è che questi problemi non vanno via con gli ORM, ma semplicemente passano al livello di presentazione. Invece di creare VO / DTO per le query, si creano oggetti di presentazione personalizzati, in genere uno per ogni vista. Come va meglio? IMHO non lo è.

Ne ho scritto in ORM o SQL: ci siamo ancora? .

La mia tecnologia di persistenza di scelta (in Java) in questi giorni è ibatis. È un wrapper piuttosto sottile attorno a SQL che fa il 90% + di ciò che JPA può fare (può persino fare un caricamento lento delle relazioni sebbene non sia ben documentato) ma con un sovraccarico molto meno (in termini di complessità e codice reale).

Questo è successo l'anno scorso in un'applicazione GWT che stavo scrivendo. Molta traduzione da EclipseLink a oggetti di presentazione nell'implementazione del servizio. Se stessimo usando ibatis sarebbe stato molto più semplice creare gli oggetti appropriati con ibatis e poi passarli su e giù per lo stack. Alcuni puristi potrebbero obiettare che si tratta di Bad ™. Forse è così (in teoria) ma ti dico una cosa: avrebbe portato a un codice più semplice, uno stack più semplice e una maggiore produttività.


2
Sono stato ispirato a pubblicare un'altra domanda (anche se wiki della community) solo per raccogliere risorse su cose come questa. Per quanto riguarda l'ultimo paragrafo: mi piace la semplicità. Probabilmente troppo.
hydrapheetz,

3
iBATIS è fantastico, ma forse ti dispiacerebbe provare jOOQ: jooq.sourceforge.net . Il suo obiettivo principale è proprio quello di stare vicino a SQL per i 6 motivi che hai citato.
Lukas Eder,

5
+1 per il punto 3. Molti ritengono che l'utilizzo di ORM ti solleva dalla conoscenza approfondita di SQL. Il fatto è che una volta che puoi / impara a fare ginnastica con SQL, probabilmente ti ritroverai ad allontanarti da ORM ... molto rapidamente.
Ryan Fernandes,

4
Quindi, ora è la fine del 2013 e, come tutti sappiamo, nulla potrebbe essere più fuorviante dei "vecchi fatti" - quindi posso chiederti se i tuoi punti sono sempre gli stessi? In caso contrario, sarebbe bello se tu potessi scrivere un post sul blog / aggiornare la tua risposta di conseguenza.
Dominik il

3
var non produce un tipo dinamico in .NET, le variabili con la parola chiave dinamica sono tipi dinamici in .NET. var è ancora digitando staticamente. Vedi stackoverflow.com/questions/961581/…
Fazi

45

Dico semplice SQL per R ead, ORM per CUD .

Le prestazioni sono qualcosa di cui mi preoccupo sempre, specialmente nelle applicazioni web, ma anche la manutenibilità e la leggibilità del codice. Per risolvere questi problemi ho scritto SqlBuilder .


1
Cos'è il CUD? Non riesco a trovare la definizione.
Kimchi Man,

27
@KimchiMan CRUD senza R.
Max Toro

3
CUD - Crea, aggiorna, elimina.
Combina il

14

L'ORM non è solo portabilità (il che è difficile da ottenere anche con gli ORM, del resto). Ciò che ti dà è fondamentalmente uno strato di astrazione su un archivio persistente, quando uno strumento ORM ti libera dalla scrittura di query SQL sulla piastra (seleziona per PK o per predicati, inserti, aggiornamenti ed eliminazioni) e ti consente di concentrarti sul dominio del problema.


3
Stavo pensando a qualcosa di più vicino alla portabilità in tutti i tipi di database. Non dovrei pubblicare domande a tarda notte.
hydrapheetz,

1
Questo è esattamente quello che stavo dicendo: anche gli scenari più elementari possono potenzialmente essere soggetti a errori in diversi DBMS - ad esempio, una diversa gestione dei NULL.
Anton Gogolev,

Un ORM ti dà uno strato di astrazione sulle relazioni tra gli oggetti, ma non vi è alcun grande vantaggio per quanto riguarda le query sulla piastra di caldaia che menzioni. In un'app JDBC è possibile scrivere quei tipi di query con una piccola quantità di codice in una superclasse astratta o in una classe di utilità. Non è necessario ripetere la piastra della caldaia per ogni nuova tabella.
Kevin Stembridge,

11

Qualsiasi progetto rispettabile avrà bisogno di qualche astrazione per il database, solo per gestire la mancata corrispondenza dell'impedenza. Ma il primo passo più semplice (e adeguato per la maggior parte dei casi) mi aspetterei sarebbe un DAL, non un ORM dei pesi massimi. Le tue uniche opzioni non sono quelle alle estremità dello spettro.


MODIFICA in risposta a un commento che mi chiede di descrivere come distinguo DAL da ORM:

Un DAL è ciò che scrivi tu stesso, magari a partire da una classe che incapsula semplicemente una tabella e ne mappa i campi alle proprietà. Un ORM è un codice che non scrivi o meccanismi di astrazione dedotti da altre proprietà del tuo schema dbms, principalmente PK e FK. (È qui che scopri se le astrazioni automatiche iniziano a perdere o no. Preferisco informarle intenzionalmente, ma potrebbe essere solo la mia preferenza personale).


2
Dove traccia il confine tra cos'è un DAL e cos'è un ORM?
caos,

4
Quindi, se sei l'autore di un ORM, il tuo ORM si trasforma automaticamente in un DAL? :)
Bombe

DAL = livello di persistenza e ORM è uno strumento che si utilizza all'interno di DAL per eseguire operazioni CRUD nell'archivio dati.
Vahid Ghadiri,

7

Ogni strumento ha il suo scopo e la sua visione. Ho creato http://www.jooq.org/ esattamente per soddisfare le tue esigenze, anche se iBatis è probabilmente una buona soluzione anche per te.

jOOQ ha funzionalità ORM di base, ma si concentra principalmente sulle cose di cui la maggior parte degli sviluppatori ha più bisogno, quando cercano di trovare l'ORM migliore per le loro esigenze:

  • generazione del codice
  • associazione variabile (è un dolore in JDBC)
  • Astrazione della sintassi SQL (per evitare errori di sintassi)

Ma spesso vanno troppo lontano e forniscono così tanta astrazione, non penseresti che stiano correndo contro un RDBMS. D'altra parte, hai scelto un RDBMS proprio perché

  • è una solida fonte di dati
  • SQL può fare molte cose buone e performanti (selezioni nidificate, unioni, join complessi, ecc.). Spesso gli ORM non possono fare queste cose.
  • puoi gestire tu stesso transazioni e sessioni
  • hai UDT e procedure memorizzate

jOOQ affronta esattamente questi punti. Funzionerà come JDBC, ma senza il dolore.


6

Il dilemma se utilizzare o meno un framework è abbastanza comune nello scenario di sviluppo software moderno.

Ciò che è importante capire è che ogni framework o approccio ha i suoi pro e contro - per esempio nella nostra esperienza abbiamo scoperto che ORM è utile quando si tratta di transazioni, ad esempio operazioni di inserimento / aggiornamento / eliminazione - ma quando si tratta di recuperare dati con complessi risultati diventa importante valutare le prestazioni e l'efficacia dello strumento ORM.

Inoltre, è importante capire che non è obbligatorio selezionare un quadro o un approccio e implementare tutto ciò. Ciò che intendiamo con questo è che possiamo avere un mix di ORM e linguaggio di query nativo. Molti framework ORM forniscono punti di estensione al plug-in in SQL nativo. Dovremmo cercare di non utilizzare eccessivamente un framework o un approccio. Siamo in grado di combinare determinati framework o approcci e fornire una soluzione appropriata.

È possibile utilizzare ORM per l'inserimento, l'aggiornamento, l'eliminazione, il controllo delle versioni con un elevato livello di concorrenza e è possibile utilizzare SQL nativo per la generazione di report e l'elenco lungo


3
Perché un ORM è migliore per l'alta concorrenza?
user359996

6

La chiave che ha fatto volare il mio ORM è stata la generazione del codice. Sono d'accordo che il percorso ORM non è il più veloce, in termini di prestazioni del codice. Ma quando hai un team medio-grande, il DB sta cambiando rapidamente la capacità di rigenerare classi e mappature dal DB come parte del processo di compilazione è qualcosa di brillante da vedere, specialmente quando usi CI. Quindi il tuo codice potrebbe non essere il più veloce, ma lo sarà la tua codifica - so quale prenderei nella maggior parte dei progetti.

La mia raccomandazione è di sviluppare usando un ORM mentre lo Schema è ancora fluido, usare la profilatura per trovare i colli di bottiglia, quindi mettere a punto quelle aree che ne hanno bisogno usando SQL grezzo.

Un altro pensiero, la memorizzazione nella cache integrata in Hibernate può spesso apportare enormi miglioramenti delle prestazioni se utilizzata nel modo giusto. Non è più necessario tornare al DB per leggere i dati di riferimento.


2
Assolutamente una questione di gusti personali. Per me, la generazione di codice è un difetto.
dkretz,

5
Leggi il secondo paragrafo .... forse anche la completezza è utile
MrTelly il

La generazione del codice è l'unico modo per eseguire determinate attività più rapidamente. Come tutti gli strumenti, può essere potente o portare a un disastro. Tecnicamente tutte le lingue producono altri tipi di codice.
Banjocat,

4

Non esiste una soluzione "one-tool-fit-all", e questo vale anche per la domanda "dovrei usare un o / m o no? '.

Direi: se dovessi scrivere un'applicazione / strumento che è molto focalizzato sui "dati", senza molta altra logica, allora userei il semplice SQL, poiché SQL è il linguaggio specifico del dominio per questo tipo di applicazioni.

D'altra parte, se dovessi scrivere un'applicazione business / enterprise che contenga molta logica di "dominio", scriverei un modello di classe avanzata in grado di esprimere questo dominio in codice. In tal caso, un mappatore OR / M potrebbe essere molto utile per farlo correttamente, in quanto richiede molto codice idraulico dalle tue mani.


"Non esiste una soluzione" un solo strumento per tutti "... beh, ci dovrebbe essere.
Rushino,

1

Una delle app che ho sviluppato era un bot IRC scritto in Python. I moduli che utilizza funzionano in thread separati, ma non ho trovato un modo per gestire il threading quando si utilizza sqlite. Tuttavia, potrebbe essere meglio per una domanda separata.

Avrei dovuto semplicemente riformulare sia il titolo che la domanda reale. Non ho mai usato un DAL in precedenza, in nessuna lingua.


4
Bene, sono dell'opinione che dovresti. Il SQL grezzo dappertutto è abbastanza abominevole.
caos,

Bene sì. Di tanto in tanto c'è un pezzo di software del forum su cui ho hackerato che ha tonnellate di mysql_query () e mysql_result () dappertutto. È matto.
hydrapheetz,

Cos'è questa "app" di cui parli?
Zoran Pavlovic,

È divertente che questa domanda sia stata posta su un'app bot irc e sia diventata quella che era (una guida molto utile)! Un'app bot irc si trova su un'estremità della scala e un'applicazione che ha 50-100 + tabelle con join complessi e milioni di righe di dati con oltre 20 sviluppatori che lavorano su di essa si trova all'estremità opposta della scala. Oserei dire che quando si tratta di un'app 'irc bot' alla fine della scala, conta appena.
Manachi,

1

Utilizzare un ORM che funziona come SQL, ma fornisce controlli in fase di compilazione e sicurezza dei tipi. Come il mio preferito: Data Knowledge Objects (divulgazione: l'ho scritto)

Per esempio:

for (Bug bug : Bug.ALL.limit(100)) {
  int id = bug.getId();
  String title = bug.getTitle();
  System.out.println(id +" "+ title);
}

Streaming completo. Facile da configurare (nessuna mappatura da definire: legge gli schemi esistenti). Supporta join, transazioni, query interne, aggregazione, ecc. Praticamente tutto ciò che puoi fare in SQL. Ed è stato dimostrato da enormi set di dati (serie temporali finanziarie) fino a diventare banali (Android).


Il tuo IDE può anche fornire direttamente tali controlli statici (IDEA conosce la struttura del DB da così tanto tempo che gli dici dove si trova il DB / dove sono i file DDL, quindi può fare controlli di tipo / controlli di relazione / ecc nelle tue query / procedure SQL / qualunque cosa )
Xenos,

è utile. può farlo come parte di un passaggio build / CI? come classifica sql rispetto ad altre stringhe? può gestire la manipolazione di stringhe o solo costanti di stringhe?
keredson,

Verrò bloccato da abBlock, ma IntelliJ analizza SQL come qualsiasi altra lingua jetbrains.com/datagrip/features in modo da poterlo integrare in CI / CD / build (forse chiedendo al team IJ di isolare il codice di analisi SQL? Forse Sonar già ha un tale parser). L'analisi porta il tipo di dati in modo da poter aggiungere controlli su di essi (l'ho fatto con un plug-in personalizzato) o controlli come "le colonne JOIN hanno un indice FK?" ecc. Questi sarebbero netti miglioramenti alle ispezioni SQL native di IJ
Xenos,

1

So che questa domanda è molto vecchia, ma ho pensato che avrei pubblicato una risposta nel caso qualcuno la incontrasse come me. Gli ORM hanno fatto molta strada. Alcuni di essi ti danno il meglio dei due mondi: rendere lo sviluppo più produttivo e mantenere le prestazioni.

Dai un'occhiata a SQL Data ( http://sqldata.codeplex.com ). È un ORM molto leggero per c # che copre tutte le basi.

Cordiali saluti, sono l'autore di SQL Data.


1

Vorrei aggiungere la mia voce al coro di risposte che dicono "C'è una via di mezzo!".

Per un programmatore di applicazioni, SQL è una combinazione di cose che potresti voler controllare e cose che quasi sicuramente non vuoi essere disturbato a controllare.

Quello che ho sempre desiderato è un livello (chiamalo DAL, ORM o micro-ORM, non mi importa quale) che si occuperà delle decisioni completamente prevedibili (come scrivere le parole chiave SQL, dove vanno le parentesi, quando inventare alias di colonna, quali colonne creare per una classe che contiene due float e un int ...), lasciandomi responsabile degli aspetti di livello superiore dell'SQL, ovvero come organizzare JOIN, calcoli sul lato server, DISTINCT, GROUP BY, sottoquery scalari, ecc.

Quindi ho scritto qualcosa che fa questo: http://quince-lib.com/

È per C ++: non so se questo sia il linguaggio che stai usando, ma allo stesso tempo potrebbe essere interessante vedere questo approccio su come potrebbe apparire una "via di mezzo".

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.