Utilizzo di SPID nelle tabelle DB (anziché nella variabile tabella)


8

Database transazionale utilizzato per la prenotazione di cose ...

Al nostro fornitore è stato chiesto di sostituire #temptables con @tablevariables (a causa di pesanti blocchi di compilazione) ma invece sono stati sostituiti con una tabella effettiva che aggiunge SPID come colonna per garantire che la procedura memorizzata agisca solo sulle righe applicabili.

Vedi qualche rischio in questo metodo di funzionamento? Prima che tutte le transazioni fossero isolate all'interno della propria transazione ... Temevo che potremmo finire per bloccare un po 'questa tabella, ma la loro opinione è che SQL usi il blocco a livello di riga e questo non creerà più blocchi.

Versione SQL Server: 2016 Enterprise - 13.0.5216.0


CREATE TABLE dbo.qryTransactions (
    ID int IDENTITY (0,1) NOT NULL CONSTRAINT pk_qryTransactions PRIMARY KEY CLUSTERED,
    spid int NOT NULL,
    OrderID int,
    ItemID int,
    TimeTransactionStart datetime,
    TimeTransactionEnd datetime,
...other fields
    )

CREATE INDEX idx_qryTransactions_spidID ON qryTransactions (spid, ID) INCLUDE (ItemID, OrderID, TimeTransactionStart, TimeTransactionEnd)

1
Dipende. Quante sessioni utilizzano contemporaneamente la tabella, quanto sono attive le sessioni, quanti record sono presenti nella tabella, i record in questa nuova tabella vengono eliminati o rimangono, ecc.? 5 sessioni, nessun grosso problema. 500 sessioni, è molto probabile che si verifichi un blocco che non vedresti con tabelle / variabili temporanee locali per ogni sessione.
John Eisbrener,

Quale versione di SQL Server stai usando?
Anthony Genovese,

2016 Enterprise - 13.0.5216.0
uscita dal

I record per la tabella che colpisce la sessione saranno 1-50 ... verranno eliminati, quindi probabilmente la tabella stessa non otterrà più di 1.000 righe contemporaneamente ... sessioni simultanee probabilmente intorno al 50 ....
outjet

1
Se sei costretto a seguire questo percorso (prova ad evitarlo), prenderei seriamente in considerazione il partizionamento sul valore spid, assicurandomi che l'escalation del blocco sulla tabella sia impostata su AUTO. Quindi almeno la cancellazione dei dati di uno specifico spid potrebbe essere eseguita in un interruttore e troncare l'operazione.
Jonathan Fite,

Risposte:


5

Un po 'più sconclusionato di quanto possa rientrare in un blocco di commenti ... e desidera evidenziare un commento fatto dall'OP in risposta alla risposta di Ray:

  • parent parent (Common_InsertOrders_1) crea una tabella temporanea
  • un proc figlio (InsertOrders) interroga la tabella temporanea
  • i blocchi di compilazione vengono visualizzati per il proc figlio (InsertOrders)

Si spegne leggermente per un minuto ... su ciò che accadrebbe con questo scenario è Sybase ASE ...

  • ogni tabella temporanea ottiene un ID oggetto univoco (certo, l'id oggetto potrebbe essere riutilizzato ad un certo punto, ma questo è raro e certamente non accadrà per sessioni simultanee)
  • Sybase ASE forza normalmente una ricompilazione su ogni esecuzione del proc figlio a causa della modifica dell'ID oggetto per la tabella temporanea
  • Sybase ASE imporrà inoltre una ricompilazione del proc figlio se rileva che la struttura della tabella temporanea è cambiata (ad esempio, diverso numero di colonne, nomi di colonne / tipi di dati / nullità diversi) tra le invocazioni di proc memorizzate
  • le versioni più recenti di Sybase ASE hanno una configurazione che (efficacemente) dice al compilatore di ignorare le modifiche negli ID degli oggetti della tabella temporanea eliminando così la ricompilazione del proc figlio (NOTA: le ricompilazioni si verificheranno comunque se la struttura della tabella cambia)

Torna al problema del PO (blocchi di compilazione sul proc figlio) ...

  • esiste la possibilità che alcune vestigia del comportamento di Sybase ASE possano ancora risiedere in SQL Server (da quando i due prodotti erano piselli in un baccello)?
  • ci sono configurazioni di SQL Server che potrebbero ridurre (eliminare?) le ricompilazioni del proc figlio (se dovuto a cambiamenti nell'ID oggetto)?
  • l'OP può verificare che il proc parent stia creando ogni volta la tabella temporanea con la stessa struttura / DDL esatta?

Per quanto riguarda l'idea di utilizzare una singola tabella permanente con @@ SPID per differenziare le righe tra le sessioni ... state lì, visto che ... schifo ; problemi ricorrenti:

  • come / quando ripulire le file orfane
  • il riutilizzo di @@ SPID da parte del motore di database potrebbe causare problemi di accuratezza dei dati in presenza di dati orfani (o durante la pulizia di dati orfani, ad esempio, eliminare dove @@ SPID = 10 ma c'è una nuova sessione / corrente / attiva con @ @ SPID = 10 => la pulizia cancella troppi dati)
  • potenziale per l'escalation dei blocchi dai blocchi di riga ai blocchi di pagine / tabelle
  • se la tabella ha indici allora potenziale (b) blocco durante l'aggiornamento degli indici
  • a seconda del database in cui risiede la tabella, è possibile che si verifichino molte più attività per la scrittura sul dispositivo di registro (in Sybase ASE è possibile disabilitare efficacemente la registrazione in tempdb)
  • anche i blocchi a livello di riga (esclusivi) possono bloccare altre sessioni (dipende dal livello di isolamento e se una sessione può scansionare o saltare detti blocchi esclusivi)

Vorrei tornare indietro e (ri) studiare il problema di root (blocchi di ricompilazione sul proc figlio) e vedere se c'è un modo per ridurre (eliminare?) Detti blocchi di compilazione. [Sfortunatamente la mia conoscenza di SQL Server su questi problemi è ... NULL ... quindi sarei interessato all'input di alcuni esperti del compilatore di SQL Server.]


1
Sono d'accordo, penso che occorra dedicare più tempo all'investigazione dei blocchi di compilazione. Questo ha alcuni punti da indagare. support.microsoft.com/en-us/help/263889/…
Jonathan Fite,

8

Mi sembra che usare @@SPIDsimili sia come chiedere problemi.

Gli ID di sessione vengono riutilizzati frequentemente; non appena una connessione utente si disconnette, quell'ID sessione è disponibile per essere riutilizzato ed è probabile che venga utilizzato dalla sessione successiva che tenta di connettersi.

Per farlo funzionare almeno in modo semi-affidabile, è necessario un trigger di accesso che elimini le righe precedenti dalla tabella con lo stesso @@SPID. Se lo fai, probabilmente vedrai molti blocchi sulla tabella usando la @@SPIDcolonna.

SQL Server utilizza infatti il ​​blocco delle righe, ma utilizza anche il blocco delle pagine e il blocco delle tabelle. Certo, potresti essere in grado di mitigarlo tramite una buona indicizzazione, ma questo mi sembra ancora un anti-pattern.

Se la procedura memorizzata è l' unico metodo utilizzato per accedere alle tabelle interessate, è possibile indagare utilizzando un blocco dell'applicazione, sp_getapplockessenzialmente per serializzare l'accesso alle parti pertinenti. I documenti per sp_getapplock sono qui . Erik Darling ha un post interessante al riguardo qui .


4

Sì, vedo dei rischi. È ingenuo fare affidamento su SQL utilizzando il blocco delle righe. Ad esempio, sono abbastanza sicuro che inserti ed eliminazioni utilizzeranno almeno i blocchi di pagina. SQL Engine sceglie il tipo di blocco in base a diversi fattori e nessuno di questi fattori include "la loro opinione". Le soluzioni generali come il cambiamento di tabelle temporanee in variabili di tabella sono generalmente anche idee sbagliate. Le variabili di tabella sono molto utili in alcune situazioni, ma presentano limiti e problemi di prestazioni. Preferisco le tabelle temporanee nella maggior parte dei casi. Soprattutto quando la tabella conterrà più di qualche dozzina di righe. Richiederei al venditore di spiegare perché il sistema ha subito "blocchi di compilazione pesanti" e in che modo tali prestazioni sono peggiorate. Ricorda, ogni volta che guardi troverai "serrature pesanti" di qualche tipo. Ciò non significa necessariamente che i blocchi siano un problema. Max' Anche i commenti su @@ SPID sono importanti. Inoltre, il modello di transazione e l'elaborazione degli errori potrebbero rappresentare un grosso problema. Se il sistema presenta deadlock o problemi di qualità dei dati di input, l'elaborazione degli errori standard può comportare la chiusura della sessione senza il corretto ripristino della tabella qryTransactions. IMO l'approccio di soluzione errata al problema originale.


Grazie per la risposta - ai tuoi punti: le nostre tracce mostrano che LCK pesante attende un blocco di compilazione su InsertOrders di stored procedure. Esiste una procedura padre Common_InsertOrders_1 che dichiara la tabella temporanea #qryTransactions e quindi la procedura nidificata InsertOrders_2 esegue una query nella tabella temporanea. Inoltre, abbiamo appreso che c'è anche una ricompilazione frequente perché dopo 6 modifiche a una tabella temporanea vuota, qualsiasi procedura memorizzata che fa riferimento a tale tabella temporanea dovrà essere ricompilata
outjet

Esistono molte ragioni per ricompilare una procedura o un'istruzione. MarkP ne ha menzionato alcuni che si applicano in SyBase e sono sicuro che SQL Server sia simile. Il conteggio delle righe della tabella temporanea è un buon esempio e la ricompilazione non è necessariamente una cosa negativa. Le statistiche delle tabelle possono cambiare sostanzialmente il piano di query ottimale e per determinarlo è necessaria una ricompilazione. Ma voglio reiterare. Ci sarà SEMPRE un blocco superiore e ciò non significa che il blocco sia un problema. Se non vedi altre prove di un problema di prestazioni, non preoccuparti.
Ray,
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.