sql >> Database teknologi >  >> RDS >> Database

Sammenligning af SQL, forespørgselsbyggere og ORM'er


Introduktion

Brug af en database til at administrere dine applikationsdata er et af de mest almindelige valg for datapersistens. Databaser tillader hurtig informationslagring og -hentning, giver dataintegritetsgarantier og tilbyder persistens ud over levetiden af ​​en individuel applikationsinstans. Der er utallige typer af databaser tilgængelige for at opfylde dit projekts krav og dine præferencer.

Det er dog ikke altid nemt at arbejde direkte med databaser fra din applikation. Forskelle i måden datastrukturer repræsenteres på fører ofte til udfordringer. Vanskeligheden ved at udtrykke finesser om forhold mellem forskellige enheder kan også forårsage problemer. For at løse dette er der blevet skabt mange forskellige værktøjer, der hjælper med at fungere som en grænseflade mellem kerneapplikationen og datalaget.

I denne guide vil vi se på nogle af de forskelle, der opstår mellem tre almindelige tilgange:rå SQL, forespørgselsbyggere og ORM'er (objektrelationelle kortlæggere). Vi sammenligner nogle af fordelene og ulemperne ved hver tilgang og afslutter med en ordliste over almindeligt anvendte udtryk for at hjælpe dig med at blive fortrolig med nogle nøglebegreber.

Som et forenklet resumé er her et generelt overblik over hver tilgangs styrker og svagheder:

Fremgangsmåde Database / programmeringsfokuseret Hands-on ledelse Abstraktionsniveau Kompleksitetsniveau
Rå SQL database-orienteret høj ingen lav
Forespørgselsbyggere blandet lav lav lav
ORM'er programmeringsorienteret lav høj høj


Håndtering af data med rå SQL eller et andet databasenative forespørgselssprog

Nogle applikationer interfacer direkte med databasen ved at skrive og udføre forespørgsler ved hjælp af det modersmål, der understøttes af databasemotoren. Ofte er en databasedriver alt, der kræves for at forbinde, godkende og kommunikere med databaseinstansen.

Udviklere kan sende forespørgsler skrevet på databasens modersmål gennem forbindelsen. Til gengæld vil databasen levere forespørgselsresultaterne, også i et af dets oprindelige formater. For mange relationelle databaser er det foretrukne sprog for forespørgsel SQL.

De fleste relationelle databaser, såvel som nogle ikke-relationelle databaser, understøtter struktureret forespørgselssprog, også kendt som SQL, til at bygge og udføre kraftfulde forespørgsler. SQL har været brugt til at administrere data siden 1970'erne, så det er velunderstøttet og standardiseret til en vis grad.


Fordele ved indbygget forespørgsel

Brug af SQL eller et andet databasesprog har nogle klare fordele.

En fordel er, at udviklere skriver og administrerer databaseforespørgslerne og håndterer resultaterne eksplicit. Selvom dette kan være meget ekstra arbejde, betyder det, at der er få overraskelser med hensyn til, hvad databasen gemmer, hvordan den repræsenterer dine data, og hvordan den vil levere disse data, når de hentes senere. Den manglende abstraktion betyder, at der er færre "bevægelige dele", der kan føre til usikkerhed.

Et eksempel på dette er ydeevne. Mens sofistikerede abstraktionslag genererer SQL-forespørgsler ved at oversætte programmeringssætninger, kan den genererede SQL være meget ineffektiv. Unødvendige klausuler, alt for brede forespørgsler og andre uheld kan føre til langsomme databaseoperationer, der kan være skrøbelige og svære at fejlfinde. Ved at skrive indbygget i SQL kan du bruge al din domæneviden og din sunde fornuft til at undgå mange klasser af forespørgselsproblemer

En anden grund til at bruge databasenative forespørgsler er fleksibilitet. Ingen abstraktion vil sandsynligvis være så fleksibel som det oprindelige databaseforespørgselssprog. Højere abstraktionsniveauer forsøger at bygge bro mellem to forskellige paradigmer, hvilket kan begrænse de typer operationer, de kan udtrykke. Når du skriver i rå SQL, kan du dog drage fordel af alle funktionerne i din databasemotor og udtrykke mere komplekse forespørgsler.



Ulemper ved indbygget forespørgsel

Selvom native forespørgsler har nogle klare stærke sider, er det ikke uden problemer.

Når du interagerer med en database fra en applikation ved hjælp af almindelig SQL, skal du forstå den underliggende datastruktur for at sammensætte gyldige forespørgsler. Du er fuldstændig ansvarlig for at oversætte mellem de datatyper og strukturer, som din applikation anvender, og de konstruktioner, der er tilgængelige i databasesystemet.

En anden ting, du skal huske på, når du arbejder med rå SQL, er, at det er helt op til dig at styre sikkerheden ved dit input. Dette gælder især, hvis du gemmer data leveret af eksterne brugere, hvor specialfremstillede input kan få din database til at afsløre information, som du ikke havde tænkt dig at tillade.

Denne type udnyttelse kaldes SQL-injektion og er et potentielt problem, når brugerinput kan påvirke databasetilstanden. Højere abstraktionsværktøjer renser ofte brugerinput automatisk, hvilket hjælper dig med at undgå denne type problemer.

At arbejde med indfødte forespørgselssprog betyder næsten altid at komponere forespørgsler med almindelige strenge. Dette kan være en smertefuld proces i tilfælde, hvor du skal undslippe input og sammenkæde strenge for at skabe en gyldig forespørgsel. Dine databaseoperationer kan blive pakket ind i mange lag af strengmanipulation, der har et stort potentiale til at ødelægge data ved et uheld.



Native forespørgselsoversigt

Selvom vi primært har talt om SQL i dette afsnit, gælder de fleste af oplysningerne her lige godt for ethvert indfødt databaseforespørgselssprog. For at opsummere, så bringer rå SQL eller direkte brug af et hvilket som helst tilsvarende forespørgselssprog dig tættest på de abstraktioner, der bruges af databasen til at lagre og administrere dataene, men tvinger dig til at gøre alt det tunge løft ved at administrere dine data manuelt.




Administration af data med forespørgselsbyggere

En alternativ tilgang til at bruge database-native forespørgselssprog som SQL er at bruge et værktøj eller bibliotek kaldet en forespørgselsbygger til at tale med din database.


Hvad er SQL-forespørgselsbyggere?

En SQL-forespørgselsbygger tilføjer et abstraktionslag over rå database-native forespørgselssprog. De gør dette ved at formalisere forespørgselsmønstre og levere metoder eller funktioner, der tilføjer input sanitet og automatisk undslipper elementer for lettere integration i applikationer.

De strukturer og handlinger, der understøttes af databaselaget, er stadig ret genkendelige, når du bruger SQL-forespørgselsbyggere. Dette giver dig mulighed for at arbejde med data programmæssigt, mens du stadig forbliver relativt tæt på dataene.

Normalt giver forespørgselsbyggere en grænseflade, der bruger metoder eller funktioner til at tilføje en betingelse til en forespørgsel. Ved at kæde metoder sammen kan udviklere komponere komplette databaseforespørgsler fra disse individuelle "klausuler".



Fordele ved SQL-forespørgselsbyggere

Fordi forespørgselsbyggere bruger de samme konstruktioner (metoder eller funktioner) som resten af ​​din applikation, finder udviklere dem ofte nemmere at administrere på lang sigt end rå databaseforespørgsler skrevet som strenge. Det er nemt at kende forskel på operatører og data, og det er nemt at dekomponere forespørgsler i logiske bidder, der håndterer specifikke dele af en forespørgsel.

For nogle udviklere er en anden fordel ved at bruge en SQL-forespørgselsbygger, at den ikke altid skjuler det underliggende forespørgselssprog. Selvom operationerne måske bruger metoder i stedet for strenge, kan den være ret gennemsigtig, hvilket gør det nemmere for dem, der er fortrolige med databasen, at forstå, hvad en operation vil gøre. Dette er ikke altid tilfældet, når der bruges større abstraktionsniveauer.

SQL-forespørgselsbyggere understøtter ofte også flere databackends, og abstraherer nogle af de subtile forskelle i forskellige relationelle databaser, for eksempel. Dette giver dig mulighed for at bruge de samme værktøjer til projekter, der bruger forskellige databaser. Det kan endda gøre migreringen til en ny database lidt lettere.



Ulemper ved SQL-forespørgselsbyggere

SQL-forespørgselsbyggere lider af nogle få af de samme ulemper som native forespørgselssprog.

En populær kritik er, at SQL-forespørgselsbyggere stadig kræver, at du forstår og redegør for databasens strukturer og muligheder. Dette er ikke en nyttig nok abstraktion for nogle udviklere. Det betyder, at du skal have et ret godt kendskab til SQL ud over den specifikke syntaks og muligheder for selve forespørgselsbyggeren.

Derudover kræver SQL-forespørgselsbyggere stadig, at du definerer, hvordan de data, du henter, relaterer til dine applikationsdata. Der er ingen automatisk synkronisering mellem dine objekter i hukommelsen og dem i databasen.

Mens forespørgselsbyggere ofte emulerer det forespørgselssprog, de er designet til at arbejde med, kan det ekstra abstraktionslag betyde, at visse operationer nogle gange ikke er mulige ved at bruge de medfølgende metoder. Normalt er der en "rå"-tilstand til at sende forespørgsler direkte til backend og omgå forespørgselsbyggerens typiske grænseflade, men dette omgår problemet i stedet for at løse det.



Oversigt over SQL-forespørgselsbyggere

Samlet set tilbyder SQL-forespørgselsbyggere et tyndt lag af abstraktion, der specifikt retter sig mod nogle af de største smertepunkter ved at arbejde direkte med database-native sprog. SQL-forespørgselsbyggere fungerer næsten som et skabelonsystem til forespørgsler, der giver udviklere mulighed for at gå på grænsen mellem at arbejde direkte med databasen og tilføje yderligere abstraktionslag.




Håndtering af data med ORM'er

Et skridt længere op i abstraktionshierarkiet er ORM'er. ORM'er sigter generelt efter en mere fuldstændig abstraktion med håbet om at integrere med applikationsdataene mere flydende.


Hvad er ORM'er?

Objektrelationelle kortlæggere, eller ORM'er, er stykker software dedikeret til at oversætte mellem datarepræsentationerne i relationelle databaser og repræsentationen i hukommelsen, der bruges med objektorienteret programmering (OOP). ORM'en giver en objektorienteret grænseflade til data i databasen, der forsøger at bruge velkendte programmeringskoncepter og reducere mængden af ​​standardkode, der er nødvendig for at fremskynde udviklingen.

Generelt fungerer ORM'er som et abstraktionslag beregnet til at hjælpe udviklere med at arbejde med databaser uden drastisk at ændre det objektorienterede paradigme. Dette kan være nyttigt ved at reducere den mentale belastning ved at tilpasse sig detaljerne i en databases lagerformat.

Især objekter i objektorienteret programmering har en tendens til at kode en masse tilstand i dem og kan have komplekse relationer med andre objekter gennem arv og andre OOP-koncepter. At kortlægge denne information pålideligt i et tabelorienteret relationelt paradigme er ofte ikke ligetil og kan kræve en god forståelse af begge systemer. ORM'er forsøger at lette denne byrde ved at automatisere noget af denne kortlægning og ved at give udtryksfulde grænseflader til dataene i systemet.



Er udfordringerne ved ORM'er specifikke for objektorienteret programmering og relationsdatabaser?

Per definition er ORM'er specifikt designet til at interface mellem objektorienterede applikationssprog og relationelle databaser. At forsøge at kortlægge og oversætte mellem de datastrukturabstraktioner, der bruges inden for programmeringssprog, og dem, der bruges af databaselagre, er et mere generelt problem, der kan eksistere, når abstraktioner ikke stemmer overens.

Afhængigt af programmeringsparadigmet (objektorienteret, funktionelt, proceduremæssigt osv.) og databasetypen (relationel, dokument, nøgleværdi osv.), kan forskellige mængder af abstraktion være nyttige. Ofte dikterer kompleksiteten af ​​datastrukturerne i applikationen, hvor nemt det er at interface med datalageret.

Objektorienteret programmering har en tendens til at producere en masse strukturer med betydelig tilstand og relationer, der skal tages højde for. Nogle andre programmeringsparadigmer er mere eksplicitte om, hvor tilstanden er lagret, og hvordan den styres. For eksempel tillader rent funktionelle sprog ikke en tilstand, der kan ændres, så tilstand er ofte et input for funktioner eller objekter, som udsender en ny tilstand. Denne rene adskillelse af data fra handlinger samt eksplicititeten af ​​tilstandslivscyklusser kan hjælpe med at forenkle interaktionen med databasen.

Uanset hvad, er muligheden for at interface med en database gennem software, der kortlægger mellem to forskellige repræsentationer, ofte tilgængelig. Så selvom ORM'er beskriver en specifik undergruppe af disse med unikke udfordringer, kræver kortlægning mellem applikationshukommelse og vedvarende lagring ofte overvejelser uanset detaljer.



Aktiv record vs datamapper ORM'er

Forskellige ORM'er anvender forskellige strategier til at kortlægge mellem applikations- og databasestrukturer. De to hovedkategorier er det aktive registreringsmønster og datamapper-mønsteret .

Det aktive registreringsmønster forsøger at indkapsle databasens data i strukturen af ​​objekter i din kode. Objekter indeholder metoder til at gemme, opdatere eller slette fra databasen, og det er meningen, at ændringer af dine objekter let skal afspejles i databasen. Generelt repræsenterer et aktivt postobjekt i din applikation en post i en database.

Aktive registreringsimplementeringer giver dig mulighed for at administrere din database ved at oprette og forbinde klasser og instanser i din kode. Da disse generelt kortlægger klasseforekomster direkte til databaseposter, er det nemt at begrebsliggøre, hvad der er i din database, hvis du forstår, hvilke objekter der bruges i din kode.

Desværre kan dette også komme med nogle store ulemper. Applikationer har en tendens til at være meget tæt forbundet med databasen, hvilket kan forårsage problemer, når du forsøger at migrere til en ny database eller endda når du tester din kode. Din kode har en tendens til at stole på, at databasen udfylder huller, der blev fjernet fra dine objekter. Den "magiske" oversættelse mellem disse to domæner kan også føre til ydeevneproblemer, da systemet sømløst forsøger at kortlægge komplekse objekter til den underliggende datastruktur.

Datamapper-mønsteret er det andet almindelige ORM-mønster. Ligesom det aktive registreringsmønster forsøger datakortlæggeren at fungere som et uafhængigt lag mellem din kode og din database, der formidler mellem de to. Men i stedet for at forsøge at integrere objekter og databaseposter problemfrit, fokuserer den på at forsøge at afkoble og oversætte mellem dem, mens de lader dem eksistere uafhængigt. Dette kan hjælpe med at adskille din forretningslogik fra databaserelaterede detaljer, der omhandler kortlægninger, repræsentation, serialisering osv.

Så i stedet for at lade ORM-systemet finde ud af, hvordan det skal kortlægges mellem objekterne og databasetabellerne, er udvikleren ansvarlig for eksplicit at kortlægge mellem de to. Dette kan hjælpe med at undgå tæt kobling og operationer bag kulisserne på bekostning af betydeligt mere arbejde med at finde ud af passende kortlægninger.



Fordele ved ORM'er

ORM'er er populære af mange grunde.

De hjælper med at abstrahere det underliggende datadomæne til noget, der er nemt at ræsonnere om i forbindelse med din ansøgning. I stedet for at tænke på datalagring som et uafhængigt system hjælper ORM'er dig med at få adgang til og administrere datasystemer som en forlængelse af dit nuværende arbejde. Dette kan hjælpe udviklere med at arbejde hurtigere med kerneforretningslogik i stedet for at blive hængende i nuancerne i deres storage-backends.

En anden bivirkning af dette er, at ORM'er fjerner meget af den kedelplade, der er nødvendig for at interface med databaser. ORM'er kommer ofte med migreringsværktøjer, der hjælper dig med at administrere databaseskemaændringer baseret på ændringer foretaget i din kode. Du behøver ikke nødvendigvis at finde ud af det perfekte databaseskema på forhånd, hvis din ORM kan hjælpe med at administrere ændringer i databasestrukturen. Dine applikations- og databaseændringer er ofte det samme eller nært beslægtede, hvilket hjælper med at spore ændringer i din database, mens du foretager ændringer i din kode.



Ulemper ved ORM'er

ORM'er er ikke uden deres fejl. I mange tilfælde udspringer disse af de samme beslutninger, som gør ORM'er nyttige.

Et af de grundlæggende problemer med ORM'er er forsøget på at skjule detaljerne i databasens backend. Denne sløring gør arbejdet med ORM'er lettere i simple tilfælde eller på små tidsskalaer, men fører ofte til problemer i takt med kompleksiteten vokser.

Abstraktionen er aldrig 100 % komplet, og forsøg på at bruge en ORM uden at forstå det underliggende forespørgselssprog eller databasestruktur fører ofte til problematiske antagelser. Dette kan gøre fejlfinding og justering af ydeevne vanskelig eller umulig.

Det måske mest velkendte problem ved at arbejde med ORM'er er objektrelationel impedansmismatch, et udtryk, der bruges til at beskrive vanskeligheden ved at oversætte mellem objektorienteret programmering og det relationelle paradigme, der bruges af relationelle databaser. Uforeneligheden mellem datamodellerne, der bruges af disse to teknologikategorier, betyder, at yderligere, uperfekt abstraktion er nødvendig med hver stigning i kompleksitet. Objektrelationel impedansmismatch er blevet kaldt datalogiens Vietnam (med henvisning til Vietnamkrigen) på grund af dets tendens til at øge kompleksiteten over tid og føre til situationer, hvor vejene til enten succes eller kursændring er svære eller umulige.

Generelt har ORM'er en tendens til at være langsommere end alternativer, især med komplekse forespørgsler. ORM'er genererer ofte komplicerede forespørgsler til relativt simple databaseoperationer, fordi de anvender generelle mønstre, der skal være fleksible nok til at håndtere andre sager. Tilliden til, at ORM gør det rigtige under alle omstændigheder, kan føre til dyre fejl, som kan være svære at indhente.



Oversigt over ORM'er

ORM'er kan være nyttige abstraktioner, der gør arbejdet med databaser meget nemmere. De kan hjælpe dig med at designe og iterere hurtigt og bygge bro over de konceptuelle forskelle mellem applikationslogikken og databasestrukturerne. Men mange af disse fordele fungerer som et tveægget sværd. De kan forhindre dig i at forstå dine databaser og kan gøre det udfordrende at fejlsøge, ændre paradigmer eller øge ydeevnen.




Ordliste

Når du arbejder med teknologier, der forbinder databaser og applikationer, kan du støde på en eller anden terminologi, som du ikke er bekendt med. I dette afsnit vil vi kort gennemgå nogle af de mest almindelige udtryk, du kan støde på, hvoraf nogle blev dækket tidligere i denne artikel, og nogle af dem ikke.

  • Datakortlægger: En datamapper er et designmønster eller et stykke software, der kortlægger programmeringsdatastrukturer til dem, der er gemt i en database. Datakortlæggere forsøger at synkronisere ændringer mellem de to kilder, mens de holder dem uafhængige af hinanden. Kortlæggeren er selv ansvarlig for at vedligeholde en fungerende oversættelse, hvilket frigør udviklere til at iterere applikationsdatastrukturerne uden bekymring for databaserepræsentationen.
  • Databasedriver: En databasedriver er et stykke software designet til at indkapsle og muliggøre forbindelser mellem en applikation og en database. Databasedrivere abstraherer detaljerne på lavt niveau om, hvordan man laver og administrerer forbindelser og giver en samlet, programmatisk grænseflade til databasesystemet. Databasedrivere er typisk det laveste abstraktionsniveau, som udviklere bruger til at interagere med databaser, med værktøjer på højere niveau, der bygger på de muligheder, som driveren leverer.
  • Injektionsangreb: Et injektionsangreb er et angreb, hvor en ondsindet bruger forsøger at udføre uønskede databaseoperationer ved hjælp af specielt udformet input i brugervendte applikationsfelter. Ofte bruges dette til at hente data, der ikke burde være tilgængeligt, eller til at slette eller manipulere information i databasen.
  • ORM: ORM'er eller objektrelationelle kortlæggere er abstraktionslag, der oversætter mellem de datarepræsentationer, der bruges i relationelle databaser, og repræsentationen i hukommelsen, der bruges med objektorienteret programmering. ORM'en giver en objektorienteret grænseflade til data i databasen, der forsøger at reducere mængden af ​​kode og bruge velkendte arketyper til at fremskynde udviklingen.
  • Objekt-relationel impedans uoverensstemmelse: Objekt-relationel impedans mismatch refererer til vanskeligheden ved at oversætte mellem en objektorienteret applikation og en relationel database. Da datastrukturerne varierer betydeligt, kan det være svært at mutere og transskribere de programmatiske datastrukturer til det format, der bruges af storage-backend.
  • Persistensramme: En persistensramme er et middleware-abstraktionslag udviklet til at bygge bro mellem programdata og databaser. Persistensrammer kan også være ORM'er, hvis den abstraktion, de anvender, kortlægger objekter til relationelle enheder.
  • Forespørgselsværktøj: En forespørgselsbygger er et abstraktionslag, der hjælper udviklere med at få adgang til og kontrollere databaser ved at levere en kontrolleret grænseflade, der tilføjer brugervenlighed, sikkerhed eller fleksibilitetsfunktioner. Typisk er forespørgselsbyggere relativt lette, fokuserer på at lette dataadgang og datarepræsentation og forsøger ikke at oversætte dataene til et specifikt programmeringsparadigme.
  • SQL: SQL, eller struktureret forespørgselssprog, er et domænespecifikt sprog udviklet til styring af relationelle databasestyringssystemer. Det kan bruges til at forespørge, definere og manipulere data i en database såvel som deres organisatoriske strukturer. SQL er allestedsnærværende blandt relationelle databaser.


Konklusion

I denne artikel tog vi et kig på et par forskellige muligheder for grænseflader med din database fra din applikation. Vi undersøgte de forskellige abstraktionsniveauer og den fleksibilitet, der tilbydes ved at bruge database-native forespørgselssprog som SQL, ved hjælp af en forespørgselsbygger til at hjælpe sikkert med at lave forespørgsler og ORM'er for at give et mere komplet abstraktionsniveau.

Hver af disse tilgange har deres anvendelser, og nogle kan være velegnede til visse typer applikationer end andre. Det er vigtigt at forstå dine applikationskrav, din organisations databaseviden og omkostningerne ved de abstraktioner (eller mangel på samme), som du vælger at implementere. Samlet set vil en forståelse af hver tilgang give dig den bedste chance for at vælge den mulighed, der passer godt til dine projekter.




  1. Android-rumdatabasen eksporterer ikke alle data

  2. Tjek, om den aktuelle dato er mellem to datoer Oracle SQL

  3. Sådan stoppes/startes databasens postkø i SQL Server (T-SQL)

  4. hvad er en god måde at horisontal shard i postgresql