È meglio separare una query grande in più query più piccole?


13

Ci sono situazioni che richiedono una query veramente grande che unisce diverse tabelle insieme a istruzioni di sub-selezione per produrre i risultati desiderati.

La mia domanda è: dovremmo considerare l'uso di più query più piccole e portare le operazioni logiche nel livello dell'applicazione eseguendo una query sul DB in più di una chiamata o è meglio averle tutte in una volta sola?
Ad esempio, considerare la seguente query:

SELECT *
FROM   `users`
WHERE  `user_id` IN (SELECT f2.`friend_user_id`
                     FROM   `friends` AS f1
                            INNER JOIN `friends` AS f2
                              ON f1.`friend_user_id` = f2.`user_id`
                     WHERE  f2.`is_page` = 0
                            AND f1.`user_id` = "%1$d"
                            AND f2.`friend_user_id` != "%1$d"
                            AND f2.`friend_user_id` NOT IN (SELECT `friend_user_id`
                                                            FROM   `friends`
                                                            WHERE  `user_id` = "%1$d"))
       AND `user_id` NOT IN (SELECT `user_id`
                             FROM   `friend_requests`
                             WHERE  `friend_user_id` = "%1$d")
       AND `user_image` IS NOT NULL
ORDER  BY RAND() 
LIMIT %2$d

Qual è il modo migliore per farlo?

Risposte:


14

Non condividerò query complesse e di grandi dimensioni con datagod qui. Vedo questi problemi solo se disorganizzati. Per quanto riguarda le prestazioni, queste sono quasi sempre migliori perché il pianificatore ha molta più libertà su come recuperare le informazioni. Tuttavia, è necessario scrivere query di grandi dimensioni tenendo presente la manutenibilità. In generale, ho scoperto che un SQL semplice e ben strutturato è facile da eseguire il debug anche quando una singola query va avanti per oltre 200 righe. Questo perché di solito hai una buona idea del tipo di problema che stai affrontando, quindi ci sono solo alcune aree nella query che devi controllare.

I problemi di manutenzione, IME, si presentano quando la struttura di SQL si rompe. Le query lunghe e complesse nelle sottoselezioni compromettono la leggibilità e la risoluzione dei problemi, così come le viste incorporate, e entrambe dovrebbero essere evitate nelle query lunghe. Invece, usa VISUALIZZA se puoi (nota se sei su MySQL, le viste non funzionano molto bene, ma sulla maggior parte degli altri db lo fanno), e usa espressioni di tabella comuni dove quelle non funzionano (MySQL non supporta queste btw).

Le query lunghe e complesse funzionano piuttosto bene sia in termini di manutenibilità sia in termini di prestazioni in cui si mantengono semplici le clausole where e dove si fa il più possibile con i join anziché con le selezioni secondarie. L'obiettivo è farlo in modo che "i record non vengano visualizzati" ti dia alcuni punti molto specifici nella query da controllare (viene eliminato in un join o filtrato in una clausola where?) E quindi il team di manutenzione può effettivamente mantenere le cose.

Per quanto riguarda la scalabilità, tieni presente che maggiore è la flessibilità del pianificatore, anche questa è una buona cosa ...

Modifica: dici che si tratta di MySQL, quindi è improbabile che le visualizzazioni funzionino così bene e che CTE sia fuori discussione. Inoltre, l'esempio fornito non è particolarmente lungo o complesso, quindi non c'è problema.


Nota: ho avuto query (non in MySQL, ma comunque ...) che erano abbastanza lunghe e complesse che i piani di query generati non erano ottimali. In questi casi, è possibile ottenere risultati più rapidi suddividendo una query estremamente complessa in due query meno complesse. Detto questo, è raro e generalmente scriverò la query complessa e scoprirò se c'è un problema piuttosto che suddividere preventivamente la query in blocchi più piccoli.
RDFozz,

8

Come qualcuno che deve supportare / pulire queste domande grandi e complicate, direi che è molto meglio suddividerle in diversi piccoli pezzi facili da capire. Non è necessariamente migliore dal punto di vista delle prestazioni, ma almeno stai dando a SQL una migliore possibilità di elaborare un buon piano di query.

Semplifica la vita alle persone che ti seguono e diranno cose positive su di te. Rendi duro con loro e loro ti malediranno.


2
lo svantaggio di una serie di semplici query è che lo stato cambia significativamente attraverso di esse, rendendo più complesso il debug generale dell'applicazione. Vale a dire che è possibile eseguire il debug di query SQL di grandi dimensioni spesso come alberi, ma il codice dell'applicazione ottiene un'istruzione di debug tramite un'istruzione che controlla come lo stato cambia nelle istruzioni. I veri problemi hanno a che fare con il fatto che le selezioni secondarie e le viste incorporate sono anche i loro alberi .....
Chris Travers,

Nel mio caso l'unico che deve gestire il DB e il codice è me stesso. E soprattutto la mia domanda era sulle prestazioni punto la query.
Hamed Momeni,

Ragazzi, dovreste dare un'occhiata al modo in cui scrivo i miei grandi processi batch. Suddividi le cose in semplici query, molto facili da leggere. Sono di parte perché le domande che finisco per cercare di riordinare sono abitualmente lunghe più di 1000 righe.
datagod

5

I miei 2 centesimi sulle prestazioni di parole chiave e scalabilità di 2 parole chiave:

Prestazioni di query: il parallelismo di SQL Server fa già un ottimo lavoro suddividendo le query in ricerche multi-thread, quindi non sono sicuro di quanto di un miglioramento delle prestazioni di query vedrai eseguendolo per SQL Server. Dovrai guardare il piano di esecuzione per vedere quanto di un certo grado di parallelismo ottieni quando lo esegui e confronta i risultati in entrambi i modi. Se si finisce per utilizzare un suggerimento query per ottenere prestazioni uguali o migliori, IMO non ne vale la pena in quanto il suggerimento query potrebbe non essere ottimale in un secondo momento.

Scalabilità: leggere le query potrebbe essere più facile come indicato dal datagod e dividerle in query separate ha senso se è possibile utilizzare le nuove query anche in altre aree, ma se non si intende utilizzarle anche per altre chiamate, saranno ancora più processi memorizzati da gestire per 1 attività e IMO non contribuirebbe alla scalabilità.


2
RE: Riferimenti "SQL Server" sebbene l'OP non abbia specificato alcun RDBMS particolare sospetto che siano su MySQL dai tick posteriori eLIMIT
Martin Smith

@MartinSmith Sospetti correttamente. È MySQL.
Hamed Momeni,

2

Alcune volte, non c'è altra scelta che dividere la query grande / complessa in piccole query. Il modo migliore per determinare che sarebbe usare l' EXPLAINistruzione con l' SELECTistruzione. Il numero di tracce / scansioni che il tuo db sta per fare per recuperare i tuoi dati è il prodotto dei valori di "righe" restituiti dalla tua EXPLAINquery. Nel nostro caso, abbiamo avuto una query che unisce 10 tabelle. In particolare, la traccia è stata di 409 milioni di utenti che hanno bloggato sul nostro DB e hanno spinto il nostro utilizzo della CPU del nostro server DB oltre il 300%. Siamo stati in grado di recuperare le stesse informazioni suddividendo le query molto più velocemente.

Quindi, in breve, in alcuni casi ha senso dividere una query complessa / grande, ma in altri può portare a molte prestazioni o problemi di manutenibilità e questo dovrebbe essere trattato caso per caso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.