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

Devo usare una funzione JOIN o eseguire più query in una struttura ad anello?

Nessuna delle due soluzioni proposte è probabilmente ottimale, MA la soluzione 1 è IMPREVEDIBILE e quindi INTRINSECAMENTE SBAGLIATA!

Una delle prime cose che si impara quando si ha a che fare con database di grandi dimensioni è che il "modo migliore" per eseguire una query dipende spesso da fattori (denominati metadati) all'interno del database:

  • Quante righe ci sono.
  • Quante tabelle stai interrogando.
  • La dimensione di ogni riga.

Per questo motivo, è improbabile che ci sia una soluzione proiettile d'argento per il tuo problema. Il tuo database non è lo stesso del mio database, dovrai confrontare diverse ottimizzazioni se hai bisogno delle migliori prestazioni disponibili.

Probabilmente scoprirai che applica e crea indici corretti (e comprendere l'implementazione nativa degli indici in MySQL) nel tuo database fa molto di più per te.

Ci sono alcune regole d'oro con le query che raramente dovrebbero essere infrante:

  • Non eseguirli in strutture ad anello . Per quanto allettante sia spesso, il sovraccarico per la creazione di una connessione, l'esecuzione di una query e l'ottenimento di una risposta è elevato.
  • Evita SELECT * a meno che non sia necessario . La selezione di più colonne aumenterà notevolmente il sovraccarico delle tue operazioni SQL.
  • Conosci i tuoi indici . Usa il EXPLAIN funzione in modo da poter vedere quali indici vengono utilizzati, ottimizzare le query per utilizzare ciò che è disponibile e crearne di nuovi.

Per questo motivo, delle due sceglierei la seconda query (sostituendo SELECT * con solo le colonne desiderate), ma ci sono probabilmente modi migliori per strutturare la query se hai il tempo per ottimizzare.

Tuttavia, la velocità NON sii la tua unica considerazione in questo, c'è un OTTIMO motivo per non usare il suggerimento uno:

PRECEDIBILITÀ:perché i blocchi di lettura sono una buona cosa

Una delle altre risposte suggerisce che avere la tabella bloccata per un lungo periodo di tempo è una cosa negativa e che quindi la soluzione a query multiple è buona.

Direi che questo non potrebbe essere più lontano dalla verità . In effetti, direi che in molti casi la prevedibilità dell'esecuzione di un singolo blocco SELECT query è un argomento più importante PER l'esecuzione di quella query rispetto ai vantaggi di ottimizzazione e velocità.

Prima di tutto, quando eseguiamo un SELECT query (di sola lettura) su un database MyISAM o InnoDB (sistemi predefiniti per MySQL), ciò che accade è che la tabella è bloccata in lettura. Ciò impedisce che qualsiasi operazione di SCRITTURA avvenga sulla tabella fino a quando il blocco di lettura non viene ceduto (o il nostro SELECT la query viene completata o non riesce). Altro SELECT le query non sono interessate, quindi se stai eseguendo un'applicazione multi-thread, continueranno a funzionare.

Questo ritardo è una BUONA cosa. Perché, potresti chiedere? Integrità dei dati relazionali.

Facciamo un esempio:stiamo eseguendo un'operazione per ottenere un elenco di oggetti attualmente nell'inventario di un gruppo di utenti su un gioco, quindi facciamo questo join:

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

Cosa succede se, durante questa operazione di query, un utente scambia un articolo con un altro utente? Usando questa query, vediamo lo stato del gioco com'era quando abbiamo avviato la query:l'oggetto esiste una volta, nell'inventario dell'utente che lo aveva prima di eseguire la query.

Ma cosa succede se lo eseguiamo in loop?

A seconda che l'utente lo abbia scambiato prima o dopo aver letto i suoi dettagli e in quale ordine leggiamo l'inventario dei due giocatori, ci sono quattro possibilità:

  1. L'oggetto potrebbe essere mostrato nell'inventario del primo utente (scansiona utente B -> scansiona utente A -> articolo scambiato O scansiona utente B -> scansiona utente A -> articolo scambiato).
  2. L'oggetto potrebbe essere mostrato nell'inventario del secondo utente (oggetto scambiato -> scansiona utente A -> scansiona utente B OPPURE oggetto scambiato -> scansiona utente B -> scansiona utente A).
  3. L'articolo potrebbe essere mostrato in entrambi scorte (scansiona utente A -> oggetto scambiato -> scansiona utente B).
  4. L'articolo potrebbe essere mostrato in nessuno dei due delle scorte dell'utente (scansiona utente B -> articolo scambiato -> scansiona utente A).

Ciò significa che non saremmo in grado di prevedere i risultati della query o di garantire l'integrità relazionale .

Se hai intenzione di dare $ 5.000 al tizio con ID articolo 1000000 a mezzanotte di martedì, spero che tu abbia $ 10.000 a portata di mano. Se il tuo programma si basa sul fatto che gli elementi unici siano unici quando vengono scattate le istantanee, potresti sollevare un'eccezione con questo tipo di query.

Il blocco è positivo perché aumenta la prevedibilità e protegge l'integrità dei risultati.

Nota:potresti forzare il blocco di un ciclo con una transazione , ma lo farà ancora sii più lento.

Oh, e finalmente, USA DICHIARAZIONI PREPARATE!

Non dovresti mai avere una dichiarazione simile a questa:

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

mysqli ha supporto per le istruzioni preparate . Leggi di loro e usali, ti aiuteranno a evitare qualcosa di terribile accade al tuo database .