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

Skal jeg bruge en JOIN-funktion eller køre flere forespørgsler i en sløjfestruktur?

Ingen af ​​de to foreslåede løsninger er sandsynligvis optimale, MEN løsning 1 er UFORSUDSELIG og dermed iboende fejlbehæftet!

En af de første ting, du lærer, når du har at gøre med store databaser, er, at 'den bedste måde' at lave en forespørgsel på ofte afhænger af faktorer (benævnt metadata) i databasen:

  • Hvor mange rækker er der.
  • Hvor mange tabeller du forespørger på.
  • Størrelsen af ​​hver række.

På grund af dette er der usandsynligt, at der er en sølvkugleløsning på dit problem. Din database er ikke den samme som min database, du bliver nødt til at benchmarke forskellige optimeringer, hvis du har brug for den bedste tilgængelige ydeevne.

Du vil sandsynligvis opdage, at anvendelse og opbygning af korrekte indekser (og at forstå den native implementering af indekser i MySQL) i din database gør meget mere for dig.

Der er nogle gyldne regler med forespørgsler, som sjældent bør brydes:

  • Lad være med at gøre dem i sløjfestrukturer . Hvor fristende det end ofte er, er omkostningerne ved at oprette en forbindelse, udføre en forespørgsel og få et svar høje.
  • Undgå SELECT * medmindre det er nødvendigt . Hvis du vælger flere kolonner, vil det øge dine SQL-operationer betydeligt.
  • Kend dine indekser . Brug EXPLAIN funktion, så du kan se, hvilke indekser der bruges, optimere dine forespørgsler for at bruge det, der er tilgængeligt, og oprette nye.

På grund af dette ville jeg af de to gå efter den anden forespørgsel (erstatter SELECT * kun med de kolonner, du ønsker), men der er sandsynligvis bedre måder at strukturere forespørgslen på, hvis du har tid til at optimere.

Hastigheden bør dog IKKE vær din eneste overvejelse i dette, der er en STOR grund til ikke at bruge forslag et:

FORUDSIGLIGHED:hvorfor læselåse er en god ting

Et af de andre svar tyder på, at det er en dårlig ting at have bordet låst i en længere periode, og derfor er løsningen med flere forespørgsler god.

Jeg vil påstå, at dette kunne ikke være længere fra sandheden . Faktisk vil jeg påstå, at det i mange tilfælde er forudsigeligheden ved at køre en enkelt låsende SELECT forespørgsel er et større argument FOR at køre den forespørgsel end fordelene ved optimering og hastighed.

Først og fremmest, når vi kører en SELECT (skrivebeskyttet) forespørgsel på en MyISAM- eller InnoDB-database (standardsystemer til MySQL), hvad der sker er, at tabellen er læselåst. Dette forhindrer enhver SKRIV-handling i at finde sted på bordet, indtil læselåsen er overgivet (enten vores SELECT forespørgslen fuldføres eller mislykkes). Andet SELECT forespørgsler påvirkes ikke, så hvis du kører et multi-threaded program, vil de fortsætte med at fungere.

Denne forsinkelse er en GOD ting. Hvorfor, spørger du måske? Relationel dataintegritet.

Lad os tage et eksempel:vi kører en operation for at få en liste over elementer, der i øjeblikket er på lageret hos en flok brugere på et spil, så vi gør dette med at deltage:

SELECT * FROM `users` JOIN `items` ON `users`.`id`=`items`.`inventory_id` WHERE `users`.`logged_in` = 1;

Hvad sker der, hvis en bruger under denne forespørgselsoperation bytter en vare til en anden bruger? Ved at bruge denne forespørgsel ser vi spiltilstanden, som den var, da vi startede forespørgslen:elementet eksisterer én gang i inventaret hos den bruger, der havde det, før vi kørte forespørgslen.

Men hvad sker der, hvis vi kører det i en løkke?

Afhængigt af om brugeren har handlet det før eller efter, vi har læst hans detaljer, og i hvilken rækkefølge vi læser opgørelsen af ​​de to spillere, er der fire muligheder:

  1. Varen kunne blive vist i den første brugers beholdning (scanningsbruger B -> scanningsbruger A -> vare handlet ELLER scanningsbruger B -> scanningsbruger A -> handlet vare).
  2. Varen kunne blive vist i den anden brugers beholdning (handlet vare -> scanningsbruger A -> scanningsbruger B ELLER handlet vare -> scanningsbruger B -> scanningsbruger A).
  3. Elementet kunne vises i begge varebeholdninger (scan bruger A -> handlet vare -> skan bruger B).
  4. Elementet kunne blive vist i ingen af ​​delene af brugerens varebeholdninger (scan bruger B -> handlet vare -> scan bruger A).

Hvad dette betyder er, at vi ville være ude af stand til at forudsige resultaterne af forespørgslen eller sikre relationel integritet .

Hvis du planlægger at give $5.000 til manden med vare-ID 1000000 ved midnat tirsdag, håber jeg, at du har $10k ved hånden. Hvis dit program er afhængig af, at unikke elementer er unikke, når der tages snapshots, vil du muligvis rejse en undtagelse med denne form for forespørgsel.

Låsning er godt, fordi det øger forudsigeligheden og beskytter integriteten af resultater.

Bemærk:Du kan tvinge en løkke til at låse med en transaktion , men det vil stadig være langsommere.

Åh, og endelig, BRUG FORBEREDTE UDTALELSER!

Du bør aldrig har en erklæring, der ser sådan ud:

mysqli_query("SELECT * FROM Table2 WHERE ColumnAId=" . $row['ColumnAId'], $con);

mysqli har understøttelse af forberedte erklæringer . Læs om dem og brug dem, de vil hjælpe dig med at undgå at der sker noget forfærdeligt med din database .



  1. PostgreSQL - GROUP BY-klausul

  2. Fejlkode:1062. Dubleret indtastning '1' for nøglen 'PRIMÆR'

  3. UTF-8 problemer med tinymce?

  4. Udsted sammenkædede rækker med dubletter