sql >> Databasteknik >  >> RDS >> Mysql

Ska jag använda en JOIN-funktion eller köra flera frågor i en loopstruktur?

Ingen av de två föreslagna lösningarna är troligen optimala, MEN lösning 1 är OFÖRSÄTTERBAR och därmed INNEHÅLLIGT FEL!

En av de första sakerna du lär dig när du hanterar stora databaser är att "det bästa sättet" att göra en fråga ofta beror på faktorer (kallade metadata) i databasen:

  • Hur många rader finns det.
  • Hur många tabeller du frågar efter.
  • Storleken på varje rad.

På grund av detta är det osannolikt att det finns en silverkula lösning för ditt problem. Din databas är inte densamma som min databas, du måste jämföra olika optimeringar om du behöver bästa möjliga prestanda.

Du kommer förmodligen att upptäcka att tillämpa och bygga korrekta index (och att förstå den inbyggda implementeringen av index i MySQL) i din databas gör mycket mer för dig.

Det finns några gyllene regler med frågor som sällan bör brytas:

  • Gör dem inte i loopstrukturer . Hur frestande det ofta är, är det höga omkostnader för att skapa en anslutning, köra en fråga och få svar.
  • Undvik SELECT * om det inte behövs . Att välja fler kolumner kommer att avsevärt öka omkostnaderna för dina SQL-operationer.
  • Känn dina index . Använd EXPLAIN funktion så att du kan se vilka index som används, optimera dina frågor för att använda det som är tillgängligt och skapa nya.

På grund av detta, av de två skulle jag välja den andra frågan (ersätter SELECT * med bara de kolumner du vill ha), men det finns förmodligen bättre sätt att strukturera frågan om du har tid att optimera.

Hastighet bör dock INTE var din enda hänsyn i detta, det finns en STOR anledning att inte använda förslag ett:

Förutsägbarhet:varför läslås är bra

Ett av de andra svaren tyder på att det är en dålig sak att ha bordet låst under en lång tidsperiod, och därför är lösningen med flera frågor bra.

Jag skulle hävda att det här inte kunde vara längre från sanningen . Jag skulle faktiskt hävda att i många fall är förutsägbarheten av att köra en enda låsning SELECT query är ett större argument FÖR att köra den frågan än optimerings- och hastighetsfördelarna.

Först och främst när vi kör en SELECT (skrivskyddad) fråga på en MyISAM- eller InnoDB-databas (standardsystem för MySQL), vad som händer är att tabellen är läslåst. Detta förhindrar att alla WRITE-operationer sker på bordet tills läslåset överlämnas (antingen vår SELECT fråga slutförs eller misslyckas). Annat SELECT frågor påverkas inte, så om du kör ett flertrådigt program kommer de att fortsätta att fungera.

Denna fördröjning är en BRA sak. Varför kan du fråga dig? Relationell dataintegritet.

Låt oss ta ett exempel:vi kör en operation för att få en lista över objekt som för närvarande finns i inventeringen av ett gäng användare på ett spel, så vi gör det här gå med:

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

Vad händer om en användare under denna frågeoperation byter ut en vara till en annan användare? Med den här frågan ser vi speltillståndet som det var när vi startade frågan:objektet finns en gång, i inventeringen av användaren som hade det innan vi körde frågan.

Men vad händer om vi kör det i en loop?

Beroende på om användaren handlade det före eller efter att vi läste hans uppgifter, och i vilken ordning vi läser inventeringen av de två spelarna, finns det fyra möjligheter:

  1. Artikeln kan visas i den första användarens inventering (skanna användare B -> skanna användare A -> handlas ELLER skanna användare B -> skanna användare A -> handlas objekt).
  2. Artikeln kan visas i den andra användarens inventering (artikel som handlas -> skanna användare A -> skanna användare B ELLER handlas artikel -> skanna användare B -> skanna användare A).
  3. Objektet kan visas i båda inventeringar (skanna användare A -> handlas -> skanna användare B).
  4. Artikeln kunde visas i ingendera av användarens lager (skanna användare B -> handlas -> skanna användare A).

Vad detta betyder är att vi inte skulle kunna förutsäga resultatet av frågan eller säkerställa relationsintegritet .

Om du planerar att ge $5 000 till killen med artikel-ID 1000000 vid midnatt på tisdag, hoppas jag att du har $10k till hands. Om ditt program förlitar sig på att unika objekt är unika när ögonblicksbilder tas, kommer du möjligen att skapa ett undantag med den här typen av fråga.

Låsning är bra eftersom det ökar förutsägbarheten och skyddar integriteten resultat.

Obs! Du kan tvinga en loop att låsa med en transaktion , men det kommer fortfarande vara långsammare.

Åh, och slutligen, ANVÄND FÖRBEREDDA UTTALANDEN!

Du bör aldrig har ett uttalande som ser ut så här:

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

mysqli har stöd för förberedda uttalanden . Läs om dem och använd dem, de hjälper dig att undvika att något hemskt händer med din databas .



  1. PHP &MySQL :Visa SUMMA av något, klassificerad efter distinkt kategori

  2. Rails 3 SQL-frågaval med joins

  3. MySQL ALTER TABLE hänger sig

  4. PHP Kontrollera om strängen innehåller en bokstav