Memoria utilizzata non liberata dopo un'esportazione di inserti / BCP BULK SQL


10

Ho creato una tabella SQL molto semplice come segue

CREATE TABLE [dbo].[TickData](
[Date] [varchar](12) NULL,
[Time] [varchar](12) NOT NULL,
[Symbol] [varchar](12) NOT NULL,
[Side] [varchar](2) NOT NULL,
[Depth] [varchar](2) NOT NULL,
[Quote] [varchar](12) NOT NULL,
[Size] [varchar](18) NOT NULL
    ) ON [PRIMARY]

Ho quindi eseguito un inserto in serie da 3 gig

    BULK
    INSERT TickData
    FROM 
    'C:\SUMO.csv'
    GO

Quindi l'utilizzo della RAM per il server SQL è andato alle stelle, consumando ~ 30 Go di RAM:

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

Preferisco pensare che si tratti di un comportamento anomalo e che sia possibile intervenire per evitarlo.

EDIT:
Ok, questo sembra essere il comportamento predefinito. Giusto.
Tuttavia, perché la memoria non viene liberata a lungo dopo che Bulk Insert è terminato?

Un paio di considerazioni extra:
A partire dai commenti riguardanti il ​​server SQL che libera la memoria quando viene "detto" dal sistema operativo, la mia esperienza pratica su un server Xeon a 32 Gb a 24 core dimostra che questo è inesatto: una volta terminato un estratto BCP Memory-Voracious Ho un pool di istanze .Net della mia applicazione di elaborazione dei dati che devono elaborare i dati estratti, e vengono lasciati soffocare / lottare per condividere la memoria rimanente per provare a svolgere i loro lavori, che impiegano più a lungo rispetto a quando viene girato SQL Server spento e la memoria è disponibile per tutte le applicazioni da condividere. Devo interrompere SQL Server Agent per far sì che tutto vada liscio e impedire che le app si arrestino in modo anomalo per Articiallt causando Eccezione OutOfMemmroy. Per quanto riguarda il limite / limitazione della memoria brutale artificiale, se è disponibile memoria libera, perché non usarlo? Idealmente, preferirebbe essere dinamicamente impostato per adattarsi a ciò che è disponibile piuttosto che limitarsi forzatamente "in modo casuale". Ma suppongo che questo sia un design originale, quindi caso chiuso su quest'ultimo punto.


6
Perché SQL Server dovrebbe liberare memoria? Se è necessario che la memoria esegua questa operazione una volta, ne avrà bisogno di nuovo. Se SQL Server rilasciasse la memoria, per cosa la useresti? Perché la memoria deve essere libera? Se usi la memoria per qualcos'altro, questo inserto di massa viene eseguito di nuovo, cosa dovrebbe succedere?
Aaron Bertrand

L'unica azione che puoi fare per evitare ciò è impostare la dimensione massima della memoria. Per "ripristinare" la memoria, è possibile riavviare il servizio SQL Server. Ovviamente, ciò rilascerà la memoria e quando il servizio si riavvierà allocerà la memoria normalmente.
TMN,

Ho ripulito l'ultima modifica. Se vuoi avere un argomento / discussione sui meriti o problemi di come SQL Server (o qualsiasi altro motore DB) è codificato, trova un posto migliore per farlo. Alla domanda originale è stata data una risposta, apparentemente corretta e sufficiente. Se questa Q continua a strisciare, potrebbe bloccarsi.
JNK,

Non c'è niente di sbagliato nel voler conoscere le risposte e discutere le metodologie, ma non qui su un sito di domande e risposte . Puoi sicuramente avere questa discussione in chat o in un forum da qualche parte, ma Stack Exchange è un po 'più strutturato e le domande di discussione verranno chiuse molto rapidamente.
JNK,

3
Inoltre, come non moderatore, mi chiedo perché stai eseguendo cose non SQL sul tuo server? La casella deve essere riservata SOLO per SQL Server, questo è come DBA 101. Il motore non è stato progettato per un ambiente di risorse condiviso.
JNK,

Risposte:


12

È normale comportamento per SQL Server allocare quanta più memoria possibile nel suo pool di buffer. I database funzionano meglio con un sacco di buffer. Se si desidera modificare il comportamento, è possibile configurare l' impostazione "Memoria massima server" . Qualche buona lettura di questo argomento è qui.


1
Per quanto riguarda la tua modifica, il commento di Aaron è positivo. Il motivo è che c'è un piccolo punto in un server di database che libera memoria. SQL Server risponderà alla pressione della memoria e rilascerà la memoria se necessario, ma in realtà non dovrebbe essere necessario.
Matt Whitfield,

@MikaJacobi Siamo spiacenti, ma la tua seconda modifica è sbagliata. Da una mentalità da sviluppatore capisco il tuo punto di vista, ma c'è una differenza tra la creazione di un mucchio di applicazioni che coesistono e un servizio server che dovrebbe davvero essere l'unico servizio che consuma memoria sulla macchina. Se si desidera che SQL Server si comporti come un'applicazione "normale", impostare la memoria massima e andarsene. La tua domanda era: perché funziona in questo modo, ed è stata data una risposta. Se la tua domanda ora è "beh, non mi piace che funzioni così" - scusa, ma non è più una domanda.
Aaron Bertrand

Giusto. Il mio punto di vista è solo che dovrebbe esserci un'opzione per attivarlo o disattivarlo e il presupposto che il server SQL sia l'unica applicazione su un server è davvero offensivo (potrebbe essere vero per le grandi aziende con reti di grandi dimensioni, ma non è l'unico possibile né l'impostazione più comune)
Mehdi LAMRANI

Non capisco ancora perché è necessario SQL Server per liberare memoria. Se altre applicazioni ne avranno bisogno, lo riprenderanno da SQL Server e SQL Server sarà conforme. Fino a quando quelle altre applicazioni non ne hanno bisogno, a che serve liberare la memoria?
Aaron Bertrand

1
@AaronBertrand Ok potrei sbagliarmi, ma come indicato nella mia ultima ultima modifica, questo non è ciò a cui ho assistito: la memoria non è stata liberata quando altre applicazioni non ne avevano quasi bisogno, causando crash di memoria (quindi la mia insoddisfazione ...) Comunque, chiudi l'argomento, immagino che non sia necessario discutere di più.
Mehdi LAMRANI,

7

Se vuoi davvero che il sistema operativo riprenda la memoria da SQL Server, prendi un grande file da 20 GB e copiarlo sulla rete. SQL Server rilascerà la memoria quando il sistema operativo ne ha bisogno. Ma osserverei una serie di contatori delle prestazioni mentre questo è in corso e vedo come cambiano le prestazioni del tuo BULK INSERT se lo esegui di nuovo mentre la copia è in corso o immediatamente dopo.

Se si desidera eseguire questa operazione manualmente, è necessario impostare un limite inferiore sull'impostazione della memoria massima del server di SQL Server e riavviare il servizio. Ora SQL Server non utilizzerà 28 GB anche se ne ha bisogno. Ma questo sembra limitare artificialmente SQL Server.

Quello che sembra aspettarsi è un comportamento più flessibile, in cui è possibile avere memoria libera per parte del tempo. Per quale scopo? È come ridurre un file di database per liberare spazio su disco che non è possibile utilizzare per altri scopi perché il file di database crescerà di nuovo?

È divertente, se si digita una ricerca su Google per "perché SQL Server" il completamento automatico più comune è "rilascia memoria".



"Quello che sembra aspettarsi è un comportamento più flessibile." Esattamente. Voglio che il server SQL utilizzi tutta la memoria disponibile quando è disponibile, ma quando questi momenti pesanti sono finiti, per tornare allo stato "sleep" e lasciare che le altre applicazioni che richiedono memoria facciano il loro lavoro in modo confortevole (puoi dare un'occhiata al mio nuova ultima modifica su questo punto)
Mehdi LAMRANI

Per un caso concreto che illustri il motivo per cui devo fare questo, puoi dare un'occhiata al mio ultimo commento a JNK in fondo alla domanda
Mehdi LAMRANI,

4

Questo è purtroppo di progettazione, si prega di fare riferimento a questo post. Tuttavia, in questo post ti dà alcune istruzioni su come controllarlo.

/server/251832/sql-server-bulk-insert-physical-memory-issue

Modifica allocazione memoria

La memoria non è freedattiva perché alloca la memoria in modo molto simile a un'applicazione .NET. Poiché l'allocazione della memoria è costosa, rimarrà tale allocazione a meno che il sistema operativo non lo richieda. Ma non temere, se il sistema operativo desidera la memoria, la riceverà, proprio come in un'applicazione .NET.


@MikaJacobi Certo, nessun problema. Un'altra cosa da notare, solo per sapere che SQL Server prenderà il controllo di tutti i core, quindi assicurati di limitare il numero di core disponibili. Ho visto SQL Server effettivamente distruggere il sistema operativo su cui è in esecuzione in precedenza e ho dovuto riavviare con difficoltà un data center SQL Server.

Buono a sapersi. Ho 24 core quindi questo ok per ora. Ma perché la memoria non viene liberata al termine dell'inserimento di massa?

Finché l'inserimento di massa è stato completato, se il sistema operativo ha bisogno della memoria che gli verrà assegnata, ma alloca memoria molto come un'applicazione .NET in modo che se ne ha bisogno e nessun altro può accedervi più velocemente.

La mia esperienza di prova è in contraddizione con questo (vedi ultima modifica).
Mehdi LAMRANI,
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.