La mia azienda utilizza un'applicazione che presenta problemi di prestazioni piuttosto importanti. Ci sono una serie di problemi con il database stesso su cui sto lavorando, ma molti di questi sono puramente correlati all'applicazione.
Nella mia indagine ho scoperto che ci sono milioni di query che colpiscono il database di SQL Server che interrogano tabelle vuote. Abbiamo circa 300 tabelle vuote e alcune di queste tabelle vengono interrogate fino a 100-200 volte al minuto. Le tabelle non hanno nulla a che fare con la nostra area di business e sono essenzialmente parti dell'applicazione originale che il fornitore non ha rimosso quando sono stati contratti dalla mia azienda per produrre una soluzione software per noi.
A parte il fatto che sospettiamo che il nostro registro degli errori dell'applicazione sia inondato da errori relativi a questo problema, il fornitore ci assicura che non vi è alcun impatto sulle prestazioni o sulla stabilità né per l'applicazione né per il server di database. Il registro degli errori è inondato nella misura in cui non possiamo vedere più di 2 minuti di errori per fare diagnosi.
Il costo effettivo di queste query sarà ovviamente basso in termini di cicli della CPU, ecc. Ma qualcuno può suggerire quale sarebbe l'effetto su SQL Server e l'applicazione? Sospetterei che i meccanismi effettivi dell'invio di una richiesta, della conferma, dell'elaborazione, della restituzione e del riconoscimento della ricevuta da parte dell'applicazione avrebbero un impatto sulle prestazioni.
Usiamo SQL Server 2008 R2, Oracle Weblogic 11g per l'app.
@ Frisbee- Per farla breve, ho creato una tabella contenente il testo della query che ha colpito le tabelle vuote nel database dell'app, quindi l'ho interrogato per tutti i nomi di tab che conosco vuoti e ho ottenuto un elenco molto lungo. Il massimo successo è stato di 2,7 milioni di esecuzioni in 30 giorni di attività, tenendo presente che l'app è generalmente in uso dalle 8:00 alle 18:00, quindi questi numeri sono più concentrati sulle ore operative. Più tabelle, più query, probabilmente alcuni relavent tramite join, altri no. Il colpo più alto (2,7 milioni all'epoca) fu una semplice selezione da una singola tabella vuota con una clausola where, senza join. Mi aspetto che query più grandi con join alle tabelle vuote possano includere aggiornamenti alle tabelle collegate, ma lo controllerò e aggiornerò questa domanda al più presto.
Aggiornamento: ci sono 1000 query con un numero di esecuzioni compreso tra 1043 e 4622614 (oltre 2,5 mesi). Dovrò scavare di più per scoprire da dove proviene il piano memorizzato nella cache. Questo è solo per darti un'idea dell'entità delle query. La maggior parte sono ragionevolmente complessi con oltre 20 join.
@ srutzky- sì, credo che ci sia una colonna di date relativa a quando il piano è stato compilato in modo che possa essere interessante, quindi lo controllerò. Mi chiedo che i limiti del thread possano essere un fattore quando SQL Server si trova su un cluster VMware? Presto sarà un Dell PE 730xD dedicato per fortuna.
@Frisbee - Ci scusiamo per la risposta in ritardo. Come hai suggerito, ho eseguito un select * dalla tabella vuota 10.000 volte su 24 thread utilizzando SQLQueryStress (quindi in realtà 240.000 iterazioni) e ho risposto immediatamente a 10.000 richieste batch / sec. Poi ho ridotto a 1000 volte su 24 thread e ho raggiunto poco meno di 4.000 richieste batch / sec. Ho anche provato 10.000 iterazioni su solo 12 thread (quindi 120000 iterazioni totali) e questo ha prodotto 6.505 batch al secondo. L'effetto sulla CPU è stato in realtà evidente, circa il 5-10% dell'utilizzo totale della CPU durante ogni test. Le attese di rete erano trascurabili (come 3ms con il client sulla mia workstation) ma l'impatto della CPU era sicuramente lì, il che è abbastanza conclusivo per quanto mi riguarda. Sembra ridursi all'uso della CPU e un po 'di inutili file di database IO. Le esecuzioni / secondo totali si attestano a poco meno di 3000, che è più che in produzione, tuttavia sto testando solo una delle dozzine di domande come questa. L'effetto netto di centinaia di query che colpiscono tabelle vuote a una velocità compresa tra 300-4000 volte al minuto non sarebbe quindi trascurabile quando si tratta del tempo della CPU. Tutti i test eseguiti su un PE 730xD inattivo con doppio array di flash e 256 GB di RAM, 12 core moderni.
@ srutzky- buona riflessione. SQLQueryStress sembra utilizzare il pool di connessioni per impostazione predefinita, ma ho comunque dato un'occhiata e ho scoperto che sì, la casella per il pool di connessioni è selezionata. Aggiornamento da seguire
@ srutzky- Il pool di connessioni non è apparentemente abilitato sull'applicazione o, in caso affermativo, non funziona. Ho eseguito una traccia del profiler e ho scoperto che le connessioni hanno EventSubClass "1 - Non pool" per gli eventi di accesso di controllo.
RE: Pool di connessioni - Controllato i weblogics e trovato pool di connessioni abilitato. Ho tracciato più tracce contro i segni di pool e live non trovati correttamente / affatto:
Ed ecco come appare quando eseguo una singola query senza join su una tabella popolata; le eccezioni recitavano "Si è verificato un errore di rete o specifico dell'istanza durante la creazione di una connessione a SQL Server. Il server non è stato trovato o non era accessibile. Verificare che il nome dell'istanza sia corretto e che SQL Server sia configurato per consentire connessioni remote. (provider: Named Pipes Provider, errore: 40 - Impossibile aprire una connessione a SQL Server) "Nota il contatore delle richieste batch. Il ping del server durante il periodo in cui vengono generate le eccezioni provoca una risposta ping riuscita.
Aggiornamento: due esecuzioni di test consecutive, stesso carico di lavoro (selezionare * dalla tabella di vuoto), pooling abilitato / non abilitato. Utilizzo della CPU leggermente maggiore e molti errori e non supera mai le 500 richieste batch / sec. I test mostrano 10.000 lotti / sec e nessun errore con pool attivo, e circa 400 batch / sec, quindi molti errori dovuti alla disabilitazione del pool. Mi chiedo se questi errori sono correlati a una mancanza di disponibilità della connessione?
@ srutzky- Seleziona Count (*) da sys.dm_exec_connections;
Pooling abilitato: 37 in modo coerente, anche dopo l'arresto del test di carico
Pooling disabilitato: 11-37 a seconda che si
verifichino o meno eccezioni su SQLQueryStress, ovvero: quando tali trogoli vengono visualizzati nel
grafico Batch / sec, le eccezioni si verificano su SQLQueryStress e il
numero di connessioni scende a 11, quindi si ripristina gradualmente fino a 37 quando i batch iniziano a raggiungere il picco e non si verificano eccezioni. Molto, molto interessante.
Numero massimo di connessioni su entrambe le istanze di test / live impostate sul valore predefinito di 0.
Sono stati controllati i registri dell'applicazione e non sono stati rilevati problemi di connettività, tuttavia sono disponibili solo un paio di minuti di registrazione a causa dell'elevato numero e dimensione degli errori, ovvero: molti errori di tracciabilità dello stack. Un collega sul supporto dell'app avvisa che si verifica un numero considerevole di errori HTTP relativi alla connettività. Sembrerebbe basato su questo, che per qualche ragione l'applicazione non stia raggruppando correttamente le connessioni e, di conseguenza, il server sta esaurendo ripetutamente le connessioni. Esaminerò di più i registri delle app. Mi chiedo c'è un modo per dimostrare che ciò sta accadendo nella produzione dal lato SQL Server?
@ srutzky- Grazie. Domani controllerò la configurazione della weblogic e aggiornerò. Stavo pensando però alle sole 37 connessioni: se SQLQueryStress sta eseguendo 12 thread a 10.000 iterazioni = 120.000 istruzioni select non raggruppate, non dovrebbe significare che ogni selezione crea una connessione distinta all'istanza sql?
@ srutzky- Le weblogics sono configurate per il pool di connessioni, quindi dovrebbe funzionare correttamente. Il pool di connessioni è configurato in questo modo, su ciascuno dei 4 weblogics con bilanciamento del carico:
- Capacità iniziale: 10
- Capacità massima: 50
- Capacità minima: 5
Quando aumento il numero di thread che eseguono la query di selezione da tabella vuota, il numero di connessioni raggiunge un picco di circa 47. Con il pool di connessioni disabilitato, vedo costantemente un numero massimo di richieste batch al secondo (da 10.000 a circa 400). Ciò che accadrà ogni volta è che le "eccezioni" su SQLQueryStress si verificano poco dopo che i batch / sec entrano in un trogolo. È legato alla connettività ma non riesco a capire esattamente perché questo accada. Quando nessun test è in esecuzione, #connections scende a circa 12.
Con il pool di connessioni disabilitato, non riesco a capire perché si verificano le eccezioni, ma forse si tratta di un'intera altra pila Scambio domanda / domanda per Adam Machanic?
@srutzky Mi chiedo quindi perché si verificano le eccezioni senza il pooling abilitato, anche se SQL Server non sta esaurendo le connessioni?
SELECT COUNT(*) FROM sys.dm_exec_connections;
per vedere se il valore è molto diverso tra il pooling abilitato o non. Sulla base di questi errori, penso che ci sarebbero molte più connessioni quando il pooling è disabilitato.
Pooling=false
o Max Pool Size
?