Le procedure memorizzate sono più efficienti, in generale, delle istruzioni in linea sui moderni RDBMS?[duplicare]

StackOverflow https://stackoverflow.com/questions/59880

  •  09-06-2019
  •  | 
  •  

Domanda

Questa domanda ha già una risposta qui:

La saggezza convenzionale afferma che le procedure memorizzate sono sempre più veloci.Quindi, poiché sono sempre più veloci, usali TUTTO IL TEMPO.

Sono abbastanza sicuro che ciò sia radicato in un contesto storico in cui una volta era così.Ora, non sto sostenendo che le Stored Proc non siano necessarie, ma voglio sapere in quali casi le procedure memorizzate sono necessarie nei database moderni come MySQL, SQL Server, Oracle o <Inserisci_il_tuo_DB_qui>.È eccessivo avere TUTTO l'accesso tramite procedure memorizzate?

È stato utile?

Soluzione

NOTA che questo è uno sguardo generale alle procedure memorizzate non regolate da un DBMS specifico.Alcuni DBM (e persino, diverse versioni dello stesso DBMS!) Potrebbero operare contrariamente a questo, quindi ti consigliamo di ricontrollare con i tuoi DBM target prima di supporre che tutto ciò valga ancora.

Da quasi un decennio sono un DBA di Sybase ASE, MySQL e SQL Server a intermittenza (insieme allo sviluppo di applicazioni in C, PHP, PL/SQL, C#.NET e Ruby).Quindi, non ho un’ascia particolare da affilare in questa (a volte) guerra santa.

I vantaggi prestazionali storici dei processi archiviati sono stati generalmente i seguenti (in nessun ordine particolare):

  • SQL pre-analizzato
  • Piano di esecuzione delle query pregenerato
  • Latenza di rete ridotta
  • Potenziali vantaggi della cache

SQL pre-analizzato -- vantaggi simili a quelli compilati vs.codice interpretato, tranne che a un livello molto micro.

È ancora un vantaggio? Non molto evidente sulla CPU moderna, ma se si invia una singola istruzione SQL MOLTO grande undici miliardi di volte al secondo, il sovraccarico di analisi può aumentare.

Piano di esecuzione delle query pregenerato.Se disponi di molti JOIN, le permutazioni possono diventare piuttosto ingestibili (gli ottimizzatori moderni hanno limiti e interruzioni per motivi di prestazioni).Non è raro che SQL molto complicato abbia latenze distinte e misurabili (ho visto una query complicata impiegare più di 10 secondi solo per generare un piano, prima di modificare il DBMS) dovute al tentativo dell'ottimizzatore di individuare il "quasi migliore" " progetto esecutivo.Le procedure memorizzate, generalmente, memorizzeranno questo in memoria in modo da poter evitare questo sovraccarico.

È ancora un vantaggio? La maggior parte dei DBMS (le ultime edizioni) memorizzeranno nella cache i piani di query per le SINGOLE istruzioni SQL, riducendo notevolmente il differenziale di prestazioni tra i processi memorizzati e l'SQL ad hoc.Esistono alcuni avvertimenti e casi in cui questo non è il caso, quindi dovrai eseguire il test sul DBMS di destinazione.

Inoltre, sempre più DBMS consentono di fornire piani di percorso di ottimizzazione (piani di query astratti) per ridurre significativamente i tempi di ottimizzazione (sia per SQL ad hoc che per procedure memorizzate!!).

AVVERTIMENTO I piani di query memorizzati nella cache non sono una panacea per le prestazioni.Talvolta il piano di query generato non è ottimale.Ad esempio, se invii SELECT * FROM table WHERE id BETWEEN 1 AND 99999999, il DBMS può selezionare una scansione a tavola intera anziché una scansione indice perché stai afferrando ogni riga nella tabella (quindi dice le statistiche).Se questa è la versione memorizzata nella cache, puoi ottenere prestazioni scadenti quando in seguito si invia SELECT * FROM table WHERE id BETWEEN 1 AND 2.Il ragionamento alla base di questo è al di fuori dell'ambito di questo post, ma per ulteriori letture vedi: http://www.microsoft.com/technet/prodtechnol/sql/2005/frcqupln.mspxE http://msdn.microsoft.com/en-us/library/ms181055.aspxE http://www.simple-talk.com/sql/performance/execution-plan-basics/

"In sintesi, hanno determinato che la fornitura di qualcosa di diverso dai valori comuni quando è stata eseguita una compilazione o una ricompila ha portato alla compilazione dell'ottimizzatore e alla memorizzazione nella cache del piano di query per quel particolare valore.Tuttavia, quando quel piano di query è stato riutilizzato per le successive esecuzioni della stessa query per i valori comuni ("M", "R" o "T"), ha comportato prestazioni non ottimali.Questo problema di prestazioni non ottimale esisteva fino a quando la query non è stata ricompilata.A quel punto, in base al valore del parametro @P1 fornito, la query potrebbe o non potrebbe avere un problema di prestazione ".

Latenza di rete ridottaR) Se stai eseguendo lo stesso SQL più e più volte - e l'SQL aggiunge molti KB di codice - sostituirlo con un semplice "exec foobar" può davvero aumentare.B) Le procedure memorizzate possono essere utilizzate per spostare il codice procedurale nel DBMS.Ciò evita di trasferire grandi quantità di dati al client solo per fargli inviare indietro un rivolo di informazioni (o nessuna!).Analogo a fare un JOIN nel DBMS vs.nel tuo codice (il WTF preferito da tutti!)

È ancora un vantaggio?R) Le moderne Ethernet da 1 Gb (e 10 Gb e oltre!) rendono questo davvero trascurabile.B) Dipende da quanto è satura la tua rete: perché spingere avanti e indietro diversi megabyte di dati senza una buona ragione?

Potenziali vantaggi della cacheL'esecuzione di trasformazioni di dati lato server può essere potenzialmente più rapida se si dispone di memoria sufficiente sul DBMS e i dati necessari si trovano nella memoria del server.

È ancora un vantaggio?A meno che la tua app non abbia accesso alla memoria condivisa ai dati DBMS, il vantaggio sarà sempre quello dei processi archiviati.

Naturalmente, nessuna discussione sull'ottimizzazione delle procedure memorizzate sarebbe completa senza una discussione sull'SQL parametrizzato e ad hoc.

SQL parametrizzato/preparato
Una sorta di incrocio tra procedure memorizzate e SQL ad hoc, sono istruzioni SQL incorporate in un linguaggio host che utilizza "parametri" per i valori delle query, ad esempio:

SELECT .. FROM yourtable WHERE foo = ? AND bar = ?

Questi forniscono una versione più generalizzata di una query che gli ottimizzatori moderni possono utilizzare per memorizzare nella cache (e riutilizzare) il piano di esecuzione della query, ottenendo gran parte del vantaggio in termini di prestazioni delle procedure memorizzate.

SQL ad hocBasta aprire una finestra della console sul tuo DBMS e digitare un'istruzione SQL.In passato, questi erano i "peggiori" risultati (in media) poiché il DBMS non aveva modo di pre-ottimizzare le query come nel metodo proc parametrizzato/memorizzato.

Ancora uno svantaggio?Non necessariamente.La maggior parte dei DBMS hanno la capacità di "astrarre" SQL ad hoc in versioni parametrizzate, annullando così più o meno la differenza tra i due.Alcuni lo fanno implicitamente o devono essere abilitati con l'impostazione di un comando (server SQL: http://msdn.microsoft.com/en-us/library/ms175037.aspx , Oracolo: http://www.praetoriate.com/oracle_tips_cursor_sharing.htm).

Lezioni imparate?La legge di Moore continua ad avanzare e gli ottimizzatori DBMS, con ogni versione, diventano più sofisticati.Certo, puoi inserire ogni singola stupida istruzione SQL all'interno di un processo memorizzato, ma sappi solo che i programmatori che lavorano sugli ottimizzatori sono molto intelligenti e sono continuamente alla ricerca di modi per migliorare le prestazioni.Alla fine (se non è già qui) le prestazioni SQL ad hoc diventeranno indistinguibili (in media!) dalle prestazioni delle procedure memorizzate, quindi qualsiasi tipo di massiccio l'uso delle procedure memorizzate ** esclusivamente per "motivi di prestazioni" ** mi sembra sicuramente un'ottimizzazione prematura.

Ad ogni modo, penso che se eviti i casi limite e hai un SQL abbastanza vanigliato, non noterai una differenza tra le procedure ad hoc e quelle memorizzate.

Altri suggerimenti

Motivi per utilizzare le procedure memorizzate:

  • Ridurre il traffico di rete -- devi inviare l'istruzione SQL attraverso la rete.Con sprocs è possibile eseguire SQL in batch, il che è anche più efficiente.
  • Piano di query di memorizzazione nella cache -- la prima volta che viene eseguito sproc, SQL Server crea un piano di esecuzione, che viene memorizzato nella cache per il riutilizzo.Ciò è particolarmente efficace per le query di piccole dimensioni eseguite frequentemente.
  • Possibilità di utilizzare parametri di output -- se invii SQL in linea che restituisce una riga, puoi recuperare solo un recordset.Con sproc puoi recuperarli come parametri di output, il che è notevolmente più veloce.
  • Autorizzazioni - quando invii SQL in linea, devi concedere le autorizzazioni sulle tabelle all'utente, il che garantisce molto più accesso rispetto alla semplice concessione dell'autorizzazione per eseguire uno sproc
  • Separazione della logica -- rimuovere il codice che genera SQL e separarlo nel database.
  • Possibilità di modificare senza ricompilare - questo può essere controverso.È possibile modificare l'SQL in uno sproc senza dover ricompilare l'applicazione.
  • Scopri dove viene utilizzata una tabella -- con sproc, se desideri trovare tutte le istruzioni SQL che fanno riferimento a una tabella particolare, puoi esportare il codice sproc e cercarlo.Questo è molto più semplice che cercare di trovarlo nel codice.
  • Ottimizzazione -- È più semplice per un DBA ottimizzare l'SQL e mettere a punto il database quando vengono utilizzati gli sproc.È più facile trovare indici mancanti e simili.
  • Attacchi SQL injection - L'SQL inline scritto correttamente può difendersi dagli attacchi, ma gli sproc sono migliori per questa protezione.

In molti casi, le procedure memorizzate sono in realtà più lente perché sono più generalizzate.Sebbene le procedure memorizzate possano essere altamente ottimizzate, nella mia esperienza c'è abbastanza sviluppo e attrito istituzionale da lasciarle sul posto una volta che funzionano, quindi le procedure memorizzate spesso tendono a restituire molte colonne "per ogni evenienza", perché non lo fai desideri distribuire una nuova procedura memorizzata ogni volta che cambi l'applicazione.Un OR/M, d'altro canto, richiede solo le colonne utilizzate dall'applicazione, riducendo così il traffico di rete, i join non necessari, ecc.

È un dibattito che infuria all'infinito (ad esempio, Qui).

È facile scrivere procedure memorizzate non valide quanto scrivere una logica di accesso ai dati non valida nella tua app.

La mia preferenza è per Stored Procs, ma è perché in genere lavoro con app molto grandi e complesse in un ambiente aziendale in cui sono presenti DBA dedicati responsabili del corretto funzionamento dei server di database.

In altre situazioni, sono abbastanza felice che le tecnologie di accesso ai dati come LINQ si occupino dell'ottimizzazione.

Tuttavia, le prestazioni pure non sono l'unica considerazione.Aspetti come la sicurezza e la gestione della configurazione sono in genere almeno altrettanto importanti.

Modificare:Sebbene l'articolo di Frans Bouma sia effettivamente prolisso, non coglie di gran lunga il punto per quanto riguarda la sicurezza.Anche il fatto che abbia 5 anni non aiuta la sua rilevanza.

Non vi è alcuna differenza di velocità evidente tra le procedure memorizzate e le query con parametri o preparate sulla maggior parte dei database moderni, poiché il database memorizzerà anche nella cache i piani di esecuzione per tali query.

Tieni presente che una query con parametri non è la stessa cosa di SQL ad hoc.

Il motivo principale per cui continuo a favorire le procedure memorizzate oggi ha più a che fare con la sicurezza.Se si utilizzano procedure memorizzate esclusivamente, puoi disabilitare le autorizzazioni INSERT, SELECT, UPDATE, DELETE, ALTER, DROP e CREATE ecc. per l'utente della tua applicazione, lasciandola solo con EXECUTE.

Ciò fornisce una piccola protezione extra contro 2° ordine SQL Injection.Le query con parametri proteggono solo da 1° ordine iniezione.

Ovviamente, la prestazione effettiva dovrebbe essere misurata nei singoli casi, non presupposta.Ma anche nei casi in cui le prestazioni lo sono ostacolato da una procedura memorizzata, ci sono buoni motivi per usarli:

  1. Gli sviluppatori di applicazioni non sono sempre i migliori programmatori SQL.Le procedure memorizzate nascondono SQL dall'applicazione.

  2. Le procedure memorizzate utilizzano automaticamente le variabili di associazione.Gli sviluppatori di applicazioni spesso evitano le variabili di collegamento perché sembrano codice non necessario e mostrano scarsi vantaggi nei piccoli sistemi di test.Successivamente, il mancato utilizzo delle variabili di collegamento può limitare le prestazioni dell'RDBMS.

  3. Le procedure memorizzate creano un livello di riferimento indiretto che potrebbe essere utile in seguito.È possibile modificare i dettagli di implementazione (inclusa la struttura della tabella) sul lato database senza toccare il codice dell'applicazione.

  4. L'esercizio di creazione di procedure memorizzate può essere utile per documentare tutte le interazioni del database per un sistema.Ed è più semplice aggiornare la documentazione quando le cose cambiano.

Detto questo, di solito inserisco SQL grezzo nelle mie applicazioni in modo da poterlo controllare da solo.Dipende dal team di sviluppo e dalla filosofia.

L'unico argomento che nessuno ha ancora menzionato come vantaggio delle procedure memorizzate è la sicurezza.Se crei l'applicazione esclusivamente con accesso ai dati tramite procedure memorizzate, puoi bloccare il database in modo che l'UNICO accesso avvenga tramite tali procedure memorizzate.Pertanto, anche se qualcuno ottiene un ID e una password del database, sarà limitato in ciò che potrà vedere o fare su quel database.

Nel 2007 lavoravo a un progetto in cui utilizzavamo MS SQL Server tramite un ORM.Avevamo 2 tabelle grandi e in crescita che richiedevano fino a 7-8 secondi di caricamento su SQL Server.Dopo aver creato 2 procedure SQL archiviate di grandi dimensioni e averle ottimizzate dal pianificatore di query, il tempo di caricamento di ciascun DB è sceso a meno di 20 millisecondi, quindi chiaramente ci sono ancora motivi di efficienza per utilizzare le procedure SQL archiviate.

Detto questo, abbiamo scoperto che il vantaggio più importante delle procedure memorizzate era la maggiore facilità di manutenzione, sicurezza, integrità dei dati e disaccoppiamento della logica aziendale dalla logica del middleware, avvantaggiando tutta la logica del middleware dal riutilizzo delle 2 procedure .

Il nostro fornitore ORM ha affermato come al solito che l'esecuzione di molte piccole query SQL sarebbe stata più efficiente rispetto al recupero di grandi set di dati uniti.La nostra esperienza (con nostra sorpresa) ha mostrato qualcos'altro.

Questo può ovviamente variare tra macchine, reti, sistemi operativi, server SQL, framework applicativi, framework ORM e implementazioni del linguaggio, quindi misura qualsiasi vantaggio, PENSI che potresti ottenere facendo qualcos'altro.

È stato solo dopo aver eseguito il benchmark che abbiamo scoperto che il problema era tra l'ORM e il database che si assumeva tutto il carico.

Preferisco usare gli SP quando ha senso usarli.In SQL Server, tuttavia, non vi è alcun vantaggio in termini di prestazioni per gli SP rispetto a una query parametrizzata.

Tuttavia, nel mio attuale lavoro, il mio capo ha affermato che siamo costretti a utilizzare gli SP perché i nostri clienti li richiedono.Si sentono più sicuri.Non sono stato qui abbastanza a lungo per vedere se stiamo implementando la sicurezza basata sui ruoli, ma ho la sensazione che lo stiamo facendo.

Quindi in questo caso i sentimenti del cliente prevalgono su tutti gli altri argomenti.

Per me un vantaggio delle procedure memorizzate è quello di essere indipendenti dalla lingua host:puoi passare da un'applicazione C, Python, PHP o qualsiasi altra applicazione a un altro linguaggio di programmazione senza riscrivere il codice.Inoltre, alcune funzionalità come le operazioni di massa migliorano realmente le prestazioni e non sono facilmente disponibili (non del tutto?) nelle lingue host.

Leggi quello di Frans Bouma ottimo post (se un po' di parte) su questo.

Tutto quello con cui posso parlare è SQL Server.In quella piattaforma, le procedure memorizzate sono utili perché il server memorizza il piano di esecuzione, che nella maggior parte dei casi accelera notevolmente le prestazioni.Dico "nella maggior parte dei casi", perché se l'SP ha percorsi di esecuzione molto diversi potresti ottenere prestazioni non ottimali.Tuttavia, anche in questi casi, un refactoring illuminato degli SP può accelerare le cose.

L'utilizzo di procedure memorizzate per le operazioni CRUD è probabilmente eccessivo, ma dipenderà dagli strumenti utilizzati e dalle proprie preferenze (o requisiti).Preferisco SQL in linea, ma mi assicuro di utilizzare query con parametri per prevenire attacchi SQL injection.Ne conservo una stampa fumetto xkcd come promemoria di cosa può andare storto se non stai attento.

Le procedure archiviate possono offrire vantaggi reali in termini di prestazioni quando si lavora con più set di dati per restituire un singolo set di dati.Di solito è più efficiente elaborare set di dati nella procedura memorizzata piuttosto che inviarli in rete per essere elaborati dal client.

Comprendere questo è un po' fuori tema rispetto alla domanda, ma se stai utilizzando molte procedure memorizzate, assicurati che ci sia un modo coerente per metterle sotto una sorta di controllo del codice sorgente (ad esempio, subversion o git) ed essere in grado di farlo migrare gli aggiornamenti dal sistema di sviluppo al sistema di test al sistema di produzione.

Quando questo viene fatto manualmente, senza alcun modo per verificare facilmente quale sia il codice e dove, diventa rapidamente un incubo.

Non so se sono più veloci.Mi piace usare ORM per l'accesso ai dati (per non reinventare la ruota) ma mi rendo conto che non è sempre un'opzione praticabile.

Frans Bouma ha un buon articolo su questo argomento: http://weblogs.asp.net/fbouma/archive/2003/11/18/38178.aspx

Le procedure archiviate sono ottime per i casi in cui il codice SQL viene eseguito frequentemente perché il database lo archivia in memoria con token.Se hai eseguito ripetutamente lo stesso codice al di fuori di una procedura memorizzata, probabilmente subirai un calo delle prestazioni dal database che analizza ripetutamente lo stesso codice.

In genere richiamavo spesso il codice come procedura memorizzata o come oggetto SqlCommand (.NET) ed lo eseguivo tutte le volte necessarie.

Sì, sono più veloci la maggior parte del tempo.Anche la composizione SQL è un'enorme area di ottimizzazione delle prestazioni.Se sto realizzando un'app di tipo back office, potrei saltarli, ma per qualsiasi cosa la produzione debba affrontare, li uso sicuramente per tutti i motivi per cui anche altri hanno parlato... vale a dire la sicurezza.

A PARER MIO...

Limitando le operazioni "C_UD" alle procedure memorizzate è possibile mantenere la logica dell'integrità dei dati in un'unica posizione.Ciò può essere fatto anche limitando le operazioni "C_UD" a un singolo livello intermedio.

È possibile fornire operazioni di lettura all'applicazione in modo che possano unire solo le tabelle/colonne di cui hanno bisogno.

Le procedure memorizzate possono anche essere utilizzate al posto delle query con parametri (o query ad hoc) anche per alcuni altri vantaggi:

  • Se devi correggere qualcosa (un ordinamento, ecc.) non è necessario ricompilare l'app
  • È possibile negare l'accesso a tutte le tabelle per quell'account utente, concedere l'accesso solo alle procedure memorizzate e instradare tutto l'accesso tramite le procedure memorizzate.In questo modo puoi avere una convalida personalizzata di tutti gli input molto più flessibile rispetto ai vincoli della tabella.

Traffico di rete ridotto: gli SP sono generalmente peggiori di Dynamic SQL.Poiché le persone non creano un nuovo SP per ogni selezione, se hai bisogno di una sola colonna ti viene detto di utilizzare l'SP che ha le colonne di cui hanno bisogno e di ignorare il resto.Ottieni una colonna in più e l'eventuale utilizzo in meno della rete che avevi appena andato via.Inoltre tendi ad avere molti filtri client quando vengono utilizzati SP.

memorizzazione nella cache: MS-SQL non li tratta in modo diverso, non da quando MS-SQL 2000 potrebbe essere 7 ma non ricordo.

autorizzazioni: non è un problema poiché quasi tutto ciò che faccio è Web o ho un livello applicativo intermedio che esegue tutto l'accesso al database.Gli unici software con cui lavoro che hanno accesso diretto dal client al database sono prodotti di terze parti progettati per consentire agli utenti di avere accesso diretto e si basano sulla concessione delle autorizzazioni agli utenti.E sì, il modello di sicurezza dei permessi MS-SQL FA SCHIFO!!!(non ho ancora dedicato del tempo al 2008) Come parte finale mi piacerebbe vedere un sondaggio su quante persone stanno ancora effettuando la programmazione client/server diretta rispetto alla programmazione di server di applicazioni web e intermedie;e se stanno realizzando progetti di grandi dimensioni perché nessun ORM.

Separazione: le persone si chiederebbero perché stai mettendo la logica aziendale al di fuori del livello intermedio.Inoltre, se stai cercando di separare il codice di gestione dei dati, ci sono modi per farlo senza inserirlo nel database.

Possibilità di modificare: di cosa non hai test e controllo della versione di cui devi preoccuparti?Inoltre è solo un problema con il client/server, nel mondo del web non c'è problema.

Trova la tabella: solo se riesci a identificare l'SP che la utilizza, utilizza gli strumenti del sistema di controllo della versione, di Agent Ransack o di Visual Studio per trovarla.

Ottimizzazione: il tuo DBA dovrebbe utilizzare gli strumenti del database per trovare le query che necessitano di ottimizzazione.Il database può indicare al DBA quali dichiarazioni richiedono più tempo e risorse e possono risolverle da lì.Per istruzioni SQL complesse, ai programmatori dovrebbe essere detto di parlare con il DBA se le selezioni semplici non se ne preoccupano.

Attacchi SQL injection: gli SP non offrono una protezione migliore.L'unica cosa che ottengono è che la maggior parte di loro insegna l'uso dei parametri rispetto all'SQL dinamico, la maggior parte degli esempi ignora i parametri.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top