sql >> Database >  >> RDS >> Database

SQL, querybuilders en ORM's vergelijken


Inleiding

Het gebruik van een database om uw toepassingsgegevens te beheren is een van de meest voorkomende keuzes voor gegevenspersistentie. Databases maken snelle opslag en ophalen van informatie mogelijk, bieden garanties voor gegevensintegriteit en bieden persistentie na de levensduur van een individuele applicatie-instantie. Er zijn talloze soorten databases beschikbaar om te voldoen aan de vereisten van uw project en uw voorkeuren.

Rechtstreeks werken met databases vanuit uw applicatie is echter niet altijd eenvoudig. Verschillen in de manier waarop datastructuren worden weergegeven, leiden vaak tot uitdagingen. De moeilijkheid om subtiliteiten over relaties tussen verschillende entiteiten uit te drukken, kan ook problemen veroorzaken. Om dit aan te pakken, zijn er veel verschillende tools gemaakt om te helpen fungeren als een interface tussen de kernapplicatie en de gegevenslaag.

In deze handleiding bekijken we enkele van de verschillen die zich voordoen tussen drie veelvoorkomende benaderingen:onbewerkte SQL, querybuilders en ORM's (object-relationele mappers). We zullen enkele van de voor- en nadelen van elke benadering met elkaar vergelijken en eindigen met een woordenlijst van veelgebruikte termen om u vertrouwd te maken met enkele belangrijke concepten.

Als vereenvoudigde samenvatting volgt hier een algemeen overzicht van de sterke en zwakke punten van elke benadering:

Aanpak Database / programmering gericht Hands-on beheer Niveau van abstractie Niveau van complexiteit
Onbewerkte SQL database-georiënteerd hoog geen laag
Query-builders gemengd laag laag laag
ORM's programmeergericht laag hoog hoog


Gegevens beheren met onbewerkte SQL of een andere database-native querytaal

Sommige toepassingen werken rechtstreeks met de database samen door query's te schrijven en uit te voeren in de moedertaal die door de database-engine wordt ondersteund. Vaak is een databasestuurprogramma voldoende om verbinding te maken, te verifiëren en te communiceren met de database-instantie.

Ontwikkelaars kunnen via de verbinding query's verzenden die in de moedertaal van de database zijn geschreven. In ruil daarvoor levert de database de queryresultaten, ook in een van de oorspronkelijke indelingen. Voor veel relationele databases is SQL de voorkeurstaal voor het opvragen.

De meeste relationele databases, evenals sommige niet-relationele databases, ondersteunen gestructureerde querytaal, ook wel SQL genoemd, om krachtige query's te bouwen en uit te voeren. SQL wordt al sinds de jaren 70 gebruikt om gegevens te beheren, dus het wordt goed ondersteund en tot op zekere hoogte gestandaardiseerd.


Voordelen van native query's

Het gebruik van SQL of een andere databasetaal heeft een aantal duidelijke voordelen.

Een voordeel is dat ontwikkelaars de databasequery's schrijven en beheren en de resultaten expliciet verwerken. Hoewel dit veel extra werk kan zijn, betekent dit dat er weinig verrassingen zijn met betrekking tot wat de database opslaat, hoe deze uw gegevens vertegenwoordigt en hoe deze die gegevens zal leveren wanneer deze later worden opgehaald. Het gebrek aan abstractie betekent dat er minder "bewegende delen" zijn die tot onzekerheid kunnen leiden.

Een voorbeeld hiervan zijn prestaties. Terwijl geavanceerde abstractielagen SQL-query's genereren door programmeerinstructies te vertalen, kan de gegenereerde SQL zeer inefficiënt zijn. Onnodige clausules, te brede zoekopdrachten en andere ongelukken kunnen leiden tot trage databasebewerkingen die kwetsbaar en moeilijk te debuggen kunnen zijn. Door native in SQL te schrijven, kunt u al uw domeinkennis en gezond verstand gebruiken om veel soorten queryproblemen te voorkomen

Een andere reden om database-native query's te gebruiken, is flexibiliteit. Geen enkele abstractie zal waarschijnlijk zo flexibel kunnen zijn als de native databasequery-taal. Hogere abstractieniveaus proberen de kloof tussen twee verschillende paradigma's te overbruggen, wat de soorten operaties die ze kunnen uitdrukken, kan beperken. Wanneer u echter in onbewerkte SQL schrijft, kunt u profiteren van alle functies van uw database-engine en complexere zoekopdrachten uiten.



Nadelen van native query's

Hoewel native query's een aantal sterke punten hebben, is het niet zonder problemen.

Bij interactie met een database vanuit een toepassing met gewone SQL, moet u de onderliggende gegevensstructuur begrijpen om geldige query's op te stellen. U bent volledig verantwoordelijk voor het vertalen tussen de datatypes en structuren die uw applicatie gebruikt en de constructies die beschikbaar zijn binnen het databasesysteem.

Een ander ding om in gedachten te houden wanneer u met onbewerkte SQL werkt, is dat het geheel aan u is om de veiligheid van uw invoer te beheren. Dit is met name het geval als u gegevens opslaat die zijn aangeleverd door externe gebruikers, waarbij speciaal vervaardigde invoer ertoe kan leiden dat uw database informatie vrijgeeft die u niet had willen toestaan.

Dit type exploit wordt SQL-injectie genoemd en is een potentieel probleem wanneer gebruikersinvoer de databasestatus kan beïnvloeden. Hulpprogramma's voor hogere abstractie zuiveren gebruikersinvoer vaak automatisch, zodat u dit soort problemen kunt voorkomen.

Werken met native querytalen betekent bijna altijd het opstellen van queries met reguliere strings. Dit kan een pijnlijk proces zijn in gevallen waarin u moet ontsnappen aan invoer en tekenreeksen moet samenvoegen om een ​​geldige query te maken. Uw databasebewerkingen kunnen verstrikt raken in vele lagen van stringmanipulatie die een hoog potentieel hebben om per ongeluk gegevens te manipuleren.



Samenvatting native query's

Hoewel we in deze sectie voornamelijk over SQL hebben gesproken, is de meeste informatie hier even goed van toepassing op elke native database-querytaal. Om samen te vatten:onbewerkte SQL of direct gebruik van een gelijkwaardige querytaal brengt u het dichtst bij de abstracties die door de database worden gebruikt om de gegevens op te slaan en te beheren, maar dwingt u om al het zware werk van het handmatig beheren van uw gegevens te doen.




Gegevens beheren met querybuilders

Een alternatieve benadering voor het gebruik van database-native querytalen zoals SQL is om een ​​tool of bibliotheek genaamd een querybuilder te gebruiken om met uw database te praten.


Wat zijn SQL-querybuilders?

Een SQL-querybuilder voegt een abstractielaag toe boven onbewerkte database-native querytalen. Ze doen dit door zoekpatronen te formaliseren en methoden of functies te bieden die invoersanering toevoegen en automatisch ontsnappen aan items voor eenvoudigere integratie in applicaties.

De structuren en acties die door de databaselaag worden ondersteund, zijn nog redelijk herkenbaar bij het gebruik van SQL-querybuilders. Hierdoor kunt u programmatisch met gegevens werken terwijl u toch relatief dicht bij de gegevens blijft.

Gewoonlijk bieden querybuilders een interface die methoden of functies gebruikt om een ​​voorwaarde aan een query toe te voegen. Door methoden aan elkaar te koppelen, kunnen ontwikkelaars volledige databasequery's samenstellen uit deze individuele "clausules".



Voordelen van SQL-querybuilders

Omdat querybuilders dezelfde constructies (methoden of functies) gebruiken als de rest van uw toepassing, vinden ontwikkelaars ze vaak gemakkelijker op lange termijn te beheren dan onbewerkte databasequery's die als tekenreeksen zijn geschreven. Het is eenvoudig om het verschil te zien tussen operators en gegevens en het is gemakkelijk om query's op te splitsen in logische brokken die specifieke delen van een query afhandelen.

Voor sommige ontwikkelaars is een ander voordeel van het gebruik van een SQL-querybuilder dat de onderliggende querytaal niet altijd wordt verborgen. Hoewel de bewerkingen methoden kunnen gebruiken in plaats van tekenreeksen, kan deze redelijk transparant zijn, waardoor het voor degenen die bekend zijn met de database gemakkelijker te begrijpen is wat een bewerking zal doen. Dit is niet altijd het geval bij gebruik van hogere abstractieniveaus.

SQL-querybuilders ondersteunen vaak ook meerdere data-backends, waarbij bijvoorbeeld enkele van de subtiele verschillen in verschillende relationele databases worden geabstraheerd. Hierdoor kunt u dezelfde tools gebruiken voor projecten die verschillende databases gebruiken. Het kan zelfs het migreren naar een nieuwe database iets gemakkelijker maken.



Nadelen van SQL-querybuilders

SQL-querybuilders hebben enkele van dezelfde nadelen als native querytalen.

Een veelgehoord punt van kritiek is dat voor het bouwen van SQL-query's nog steeds wordt vereist dat u de structuren en mogelijkheden van de database begrijpt en verklaart. Dit is voor sommige ontwikkelaars geen bruikbare abstractie. Dit betekent dat je een redelijk goed begrip van SQL moet hebben, naast de specifieke syntaxis en mogelijkheden van de querybuilder zelf.

Bovendien vereisen SQL-querybuilders nog steeds dat u definieert hoe de gegevens die u ophaalt zich verhouden tot uw toepassingsgegevens. Er is geen automatische synchronisatie tussen uw in-memory objecten en die in de database.

Hoewel querybuilders vaak de querytaal nabootsen waarmee ze zijn ontworpen om mee te werken, kan de extra abstractielaag betekenen dat bepaalde bewerkingen soms niet mogelijk zijn met de aangeboden methoden. Meestal is er een "onbewerkte" modus om query's rechtstreeks naar de backend te sturen, waarbij de typische interface van de querybuilder wordt omzeild, maar dit omzeilt het probleem in plaats van het op te lossen.



Samenvatting van SQL-querybuilders

Over het algemeen bieden SQL-querybuilders een dunne laag abstractie die specifiek gericht is op enkele van de belangrijkste pijnpunten van rechtstreeks werken met database-native talen. SQL-querybuilders functioneren bijna als een sjabloonsysteem voor query's, waardoor ontwikkelaars de grens kunnen overschrijden tussen rechtstreeks werken met de database en het toevoegen van extra abstractielagen.




Gegevens beheren met ORM's

Een stap verder in de abstractiehiërarchie zijn ORM's. ORM's streven over het algemeen naar een completere abstractie in de hoop dat deze soepeler met de applicatiegegevens kunnen worden geïntegreerd.


Wat zijn ORM's?

Object-relationele mappers, of ORM's, zijn stukjes software die zijn bedoeld voor het vertalen tussen de gegevensrepresentaties in relationele databases en de representatie in het geheugen die worden gebruikt bij objectgeoriënteerd programmeren (OOP). De ORM biedt een objectgeoriënteerde interface voor gegevens in de database, waarbij wordt geprobeerd bekende programmeerconcepten te gebruiken en de hoeveelheid standaardcode die nodig is om de ontwikkeling te versnellen, te verminderen.

Over het algemeen dienen ORM's als een abstractielaag die bedoeld is om ontwikkelaars te helpen met databases te werken zonder het objectgeoriënteerde paradigma drastisch te veranderen. Dit kan nuttig zijn door de mentale belasting van het aanpassen aan de specifieke kenmerken van het opslagformaat van een database te verminderen.

Met name objecten in objectgeoriënteerd programmeren hebben de neiging om veel status erin te coderen en kunnen complexe relaties hebben met andere objecten door overerving en andere OOP-concepten. Het betrouwbaar in kaart brengen van deze informatie in een tabelgeoriënteerd relationeel paradigma is vaak niet eenvoudig en vereist een goed begrip van beide systemen. ORM's proberen deze last te verlichten door een deel van deze mapping te automatiseren en door expressieve interfaces te bieden voor de gegevens in het systeem.



Zijn de uitdagingen van ORM's specifiek voor objectgeoriënteerd programmeren en relationele databases?

ORM's zijn per definitie specifiek ontworpen om te communiceren tussen objectgeoriënteerde applicatietalen en relationele databases. Het proberen in kaart te brengen en te vertalen tussen de datastructuur-abstracties die worden gebruikt in programmeertalen en die welke worden gebruikt door database-archieven is echter een meer algemeen probleem dat kan optreden wanneer abstracties niet netjes zijn uitgelijnd.

Afhankelijk van het programmeerparadigma (objectgeoriënteerd, functioneel, procedureel, enz.) en het databasetype (relationeel, document, sleutelwaarde, enz.), kunnen verschillende hoeveelheden abstractie nuttig zijn. Vaak bepaalt de complexiteit van de gegevensstructuren binnen de applicatie hoe gemakkelijk het is om te communiceren met de gegevensopslag.

Objectgeoriënteerd programmeren heeft de neiging om veel structuren te produceren met significante status en relaties waarmee rekening moet worden gehouden. Sommige andere programmeerparadigma's zijn explicieter over waar de status wordt opgeslagen en hoe deze wordt beheerd. Puur functionele talen laten bijvoorbeeld geen veranderlijke status toe, dus status is vaak een invoer voor functies of objecten die een nieuwe status uitvoeren. Deze zuivere scheiding van gegevens van acties, evenals de explicietheid van de levenscycli van de staat, kan de interactie met de database helpen vereenvoudigen.

Hoe dan ook, de optie om te communiceren met een database via software die tussen twee verschillende representaties in kaart brengt, is vaak beschikbaar. Dus hoewel ORM's een specifieke subset hiervan beschrijven met unieke uitdagingen, vereist mapping tussen applicatiegeheugen en permanente opslag vaak aandacht, ongeacht de details.



Actieve record vs data mapper ORM's

Verschillende ORM's gebruiken verschillende strategieën om tussen applicatie- en databasestructuren in kaart te brengen. De twee belangrijkste categorieën zijn het actieve recordpatroon en het data mapper-patroon .

Het actieve recordpatroon probeert de gegevens van de database in te kapselen in de structuur van objecten in uw code. Objecten bevatten methoden om de database op te slaan, bij te werken of te verwijderen en wijzigingen aan uw objecten zijn bedoeld om gemakkelijk in de database te worden weergegeven. Over het algemeen vertegenwoordigt een actief recordobject in uw toepassing een record in een database.

Met actieve recordimplementaties kunt u uw database beheren door klassen en instanties binnen uw code te maken en te verbinden. Aangezien deze klasse-instanties over het algemeen rechtstreeks aan databaserecords toewijzen, is het gemakkelijk om te conceptualiseren wat er in uw database staat als u begrijpt welke objecten in uw code worden gebruikt.

Helaas kan dit ook enkele grote nadelen met zich meebrengen. Applicaties zijn vaak erg nauw verbonden met de database, wat problemen kan veroorzaken bij het migreren naar een nieuwe database of zelfs bij het testen van uw code. Uw code heeft de neiging om op de database te vertrouwen om leemten op te vullen die uit uw objecten zijn verwijderd. De "magische" vertaling tussen deze twee domeinen kan ook leiden tot prestatieproblemen, aangezien het systeem complexe objecten naadloos in kaart probeert te brengen met de onderliggende gegevensstructuur.

Het data mapper-patroon is het andere veelvoorkomende ORM-patroon. Net als het actieve recordpatroon, probeert de datamapper te fungeren als een onafhankelijke laag tussen uw code en uw database die tussen beide bemiddelt. In plaats van te proberen objecten en databaserecords naadloos te integreren, is het echter gericht op het ontkoppelen en vertalen tussen beide, terwijl ze elk afzonderlijk bestaan. Dit kan helpen om uw bedrijfslogica te scheiden van databasegerelateerde details die te maken hebben met toewijzingen, representatie, serialisatie, enz.

Dus in plaats van het ORM-systeem te laten uitzoeken hoe de objecten en de databasetabellen moeten worden toegewezen, is de ontwikkelaar verantwoordelijk voor het expliciet in kaart brengen tussen de twee. Dit kan helpen om strakke koppelingen en operaties achter de schermen te voorkomen, wat ten koste gaat van aanzienlijk meer werk bij het uitzoeken van de juiste mappings.



Voordelen van ORM's

ORM's zijn om vele redenen populair.

Ze helpen het onderliggende datadomein te abstraheren tot iets waarover gemakkelijk te redeneren is binnen de context van uw toepassing. In plaats van dataopslag te beschouwen als een onafhankelijk systeem, helpen ORM's u toegang te krijgen tot datasystemen en deze te beheren als een verlengstuk van uw huidige werk. Dit kan ontwikkelaars helpen sneller te werken aan de logica van de kernactiviteiten in plaats van vast te lopen in de nuances van hun opslagbackends.

Een ander neveneffect hiervan is dat ORM's veel van de standaardtekst verwijderen die nodig is om te communiceren met databases. ORM's worden vaak geleverd met migratietools waarmee u wijzigingen in het databaseschema kunt beheren op basis van wijzigingen die in uw code zijn aangebracht. U hoeft niet per se het perfecte databaseschema van tevoren te bedenken als uw ORM kan helpen bij het beheren van wijzigingen in de databasestructuur. Uw applicatie- en databasewijzigingen zijn vaak hetzelfde of nauw verwant, wat helpt bij het volgen van wijzigingen in uw database terwijl u wijzigingen aanbrengt in uw code.



Nadelen van ORM's

ORM's zijn niet zonder hun gebreken. In veel gevallen komen deze voort uit dezelfde beslissingen die ORM's nuttig maken.

Een van de fundamentele problemen met ORM's is de poging om de details van de database-backend te verbergen. Deze versluiering maakt het werken met ORM's gemakkelijker in eenvoudige gevallen of op kleine tijdschalen, maar leidt vaak tot problemen naarmate de complexiteit toeneemt.

De abstractie is nooit 100% compleet en een poging om een ​​ORM te gebruiken zonder de onderliggende querytaal of databasestructuur te begrijpen, leidt vaak tot problematische veronderstellingen. Dit kan foutopsporing en prestatieafstemming moeilijk of onmogelijk maken.

Misschien wel het meest bekende probleem van het werken met ORM's is object-relationele impedantie-mismatch, een term die wordt gebruikt om de moeilijkheid te beschrijven van het vertalen tussen objectgeoriënteerd programmeren en het relationele paradigma dat wordt gebruikt door relationele databases. De onverenigbaarheden tussen de datamodellen die door deze twee categorieën technologie worden gebruikt, maken dat bij elke toename in complexiteit aanvullende, onvolmaakte abstractie nodig is. Object-relationele impedantie-mismatch wordt het Vietnam van de computerwetenschap genoemd (verwijzend naar de oorlog in Vietnam) vanwege de neiging om de complexiteit in de loop van de tijd te vergroten en tot situaties te leiden waarin de paden naar succes of verandering van koers moeilijk of onmogelijk zijn.

Over het algemeen zijn ORM's meestal langzamer dan alternatieven, vooral bij complexe zoekopdrachten. ORM's genereren vaak gecompliceerde query's voor relatief eenvoudige databasebewerkingen, omdat ze algemene patronen gebruiken die flexibel genoeg moeten zijn om andere gevallen af ​​te handelen. Het vertrouwen op de ORM om onder alle omstandigheden het juiste te doen, kan leiden tot kostbare fouten die moeilijk in te halen zijn.



Samenvatting van ORM's

ORM's kunnen nuttige abstracties zijn die het werken met databases een stuk eenvoudiger maken. Ze kunnen u helpen bij het snel ontwerpen en herhalen en overbruggen van de conceptuele verschillen tussen de toepassingslogica en databasestructuren. Veel van deze voordelen werken echter als een tweesnijdend zwaard. Ze kunnen voorkomen dat u uw databases begrijpt en kunnen het een uitdaging maken om fouten op te sporen, paradigma's te wijzigen of de prestaties te verbeteren.




Woordenlijst

Wanneer u werkt met technologieën die een interface vormen tussen databases en toepassingen, kunt u bepaalde terminologie tegenkomen die u niet kent. In dit gedeelte bespreken we kort enkele van de meest voorkomende termen die u tegen kunt komen, waarvan sommige eerder in dit artikel zijn behandeld en andere niet.

  • Datamapper: Een data mapper is een ontwerppatroon of stuk software dat programmeerdatastructuren toewijst aan de structuren die zijn opgeslagen in een database. Datamappers proberen wijzigingen tussen de twee bronnen te synchroniseren terwijl ze onafhankelijk van elkaar blijven. De mapper is zelf verantwoordelijk voor het onderhouden van een werkende vertaling, zodat ontwikkelaars de datastructuren van de applicatie kunnen herhalen zonder zich zorgen te hoeven maken over de databaserepresentatie.
  • Databasestuurprogramma: Een databasestuurprogramma is een stukje software dat is ontworpen om verbindingen tussen een toepassing en een database in te kapselen en mogelijk te maken. Databasestuurprogramma's abstraheren de details op laag niveau over het maken en beheren van verbindingen en bieden een uniforme, programmatische interface naar het databasesysteem. Doorgaans zijn databasestuurprogramma's het laagste abstractieniveau dat ontwikkelaars gebruiken om te communiceren met databases, waarbij hulpprogramma's op een hoger niveau voortbouwen op de mogelijkheden die door het stuurprogramma worden geboden.
  • Injectie-aanval: Een injectieaanval is een aanval waarbij een kwaadwillende gebruiker ongewenste databasebewerkingen probeert uit te voeren met behulp van speciaal vervaardigde invoer in gebruikersgerichte toepassingsvelden. Vaak wordt dit gebruikt om gegevens op te halen die niet toegankelijk zouden moeten zijn of om informatie in de database te verwijderen of te manipuleren.
  • ORM: ORM's, of object-relationele mappers, zijn abstractielagen die zich vertalen tussen de gegevensrepresentaties die worden gebruikt in relationele databases en de representatie in het geheugen die worden gebruikt bij objectgeoriënteerd programmeren. De ORM biedt een objectgeoriënteerde interface voor gegevens in de database, waarbij wordt geprobeerd de hoeveelheid code te verminderen en bekende archetypen te gebruiken om de ontwikkeling te versnellen.
  • Object-relationele impedantie komt niet overeen: Object-relationele impedantie-mismatch verwijst naar de moeilijkheid om te vertalen tussen een objectgeoriënteerde toepassing en een relationele database. Aangezien de datastructuren aanzienlijk variëren, kan het moeilijk zijn om de programmatische datastructuren getrouw en efficiënt te muteren en te transcriberen naar het formaat dat wordt gebruikt door de storage-backend.
  • Persistentiekader: Een persistentieframework is een middleware-abstractielaag die is ontwikkeld om de kloof tussen programmagegevens en databases te overbruggen. Persistentiekaders kunnen ook ORM's zijn als de abstractie die ze gebruiken objecten toewijst aan relationele entiteiten.
  • Query-builder: Een querybuilder is een abstractielaag die ontwikkelaars helpt bij het openen en beheren van databases door een gecontroleerde interface te bieden die bruikbaarheids-, veiligheids- of flexibiliteitsfuncties toevoegt. Querybuilders zijn doorgaans relatief licht van gewicht, richten zich op het vergemakkelijken van gegevenstoegang en gegevensrepresentatie, en proberen de gegevens niet te vertalen naar een specifiek programmeerparadigma.
  • SQL: SQL, of gestructureerde zoektaal, is een domeinspecifieke taal die is ontwikkeld voor het beheer van relationele databasebeheersystemen. Het kan worden gebruikt voor het opvragen, definiëren en manipuleren van gegevens binnen een database, evenals hun organisatiestructuren. SQL is alomtegenwoordig onder relationele databases.


Conclusie

In dit artikel hebben we een aantal verschillende opties bekeken voor de interface met uw database vanuit uw toepassing. We onderzochten de verschillende abstractieniveaus en de flexibiliteit die wordt geboden door het gebruik van database-native querytalen zoals SQL, het gebruik van een querybuilder om veilig queries te maken en ORM's om een ​​completer abstractieniveau te bieden.

Elk van deze benaderingen heeft zijn eigen gebruik en sommige kunnen zeer geschikt zijn voor bepaalde soorten toepassingen dan andere. Het is belangrijk om inzicht te krijgen in uw toepassingsvereisten, de databasekennis van uw organisatie en de kosten van de abstracties (of het ontbreken daarvan) die u wilt implementeren. Over het algemeen geeft het begrijpen van elke benadering u de beste kans om de optie te selecteren die het beste bij uw projecten past.




  1. SIGN() Functie in Oracle

  2. Waarom bespaart SQL Server DATETIME-type tijd in tikken van 1/300 van een seconde?

  3. Top 10 redenen waarom u SQL zou moeten leren

  4. Oracle DBA realtime vragen