Memoria usada no liberada después de una inserción BULK SQL / exportación BCP

10

He creado una tabla SQL muy básica de la siguiente manera

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]

Luego realicé una inserción a granel de 3 conciertos

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

Luego, el uso de RAM para el servidor SQL se disparó, consumiendo ~ 30Go de RAM:

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

Prefiero pensar que este es un comportamiento anormal y que se pueden tomar medidas para evitarlo.

EDITAR:
Ok, este parece ser el comportamiento predeterminado. Lo suficientemente justo.
Sin embargo, ¿por qué no se libera memoria mucho después de que finaliza la inserción masiva?

Un par de consideraciones adicionales:
A partir de los comentarios sobre el servidor SQL que libera la memoria cuando el sistema operativo "lo indica", mi experiencia práctica en un servidor Xeon de 32 Gb y 24 núcleos demuestra que esto es inexacto: una vez que finaliza un extracto BCP con memoria de gran volumen Tengo un grupo de instancias .Net de mi aplicación de procesamiento de datos que necesitan procesar los datos extraídos, y se quedan atorados / peleando para compartir la memoria restante para intentar realizar sus trabajos, lo que lleva mucho más tiempo que cuando se activa SQL Server apagado y la memoria está disponible para todas las aplicaciones para compartir. Tengo que detener el Agente SQL Server para que todo funcione sin problemas y evitar que las aplicaciones se bloqueen porque Articiallt causó la excepción OutOfMemmroy. En cuanto a la limitación / limitación artificial de la memoria brutal, si hay disponible memoria libre, ¿Por qué no usarlo? Idealmente, preferiría establecerse dinámicamente para adaptarse a lo que está disponible en lugar de limitarse forzosamente "al azar". Pero supongo que esto es por diseño, por lo que el caso se cerró en este último punto.

Mehdi LAMRANI
fuente
66
¿Por qué SQL Server debería liberar la memoria? Si necesitaba la memoria para realizar esta operación una vez, la necesitará nuevamente. Si SQL Server liberara la memoria, ¿para qué la usaría? ¿Por qué la memoria necesita ser libre? Si usa la memoria para otra cosa, esta inserción masiva se ejecuta nuevamente, ¿qué debería pasar?
Aaron Bertrand
La única acción que puede tomar para evitar esto es establecer el tamaño máximo de memoria. Para "recuperar" la memoria, puede reiniciar el servicio SQL Server. Obviamente, eso liberará la memoria, y cuando el servicio se reinicie, asignará la memoria normalmente.
TMN
Limpié la última edición. Si desea tener una discusión / discusión sobre los méritos o problemas de cómo se codifica SQL Server (o cualquier otro motor de base de datos), busque un mejor lugar para hacerlo. La pregunta original ha sido respondida, aparentemente correcta y suficientemente. Si esta Q sigue arrastrándose, puede bloquearse.
JNK
No hay nada de malo en querer saber respuestas y discutir metodologías, solo que no aquí en un sitio de preguntas y respuestas. Definitivamente puede tener esta discusión en el chat o en un foro en algún lugar, pero Stack Exchange es un poco más estructurado y las preguntas de discusión se cerrarán muy rápidamente.
JNK
3
Además, como no moderador, me pregunto por qué está ejecutando cosas que no son SQL en su servidor. El cuadro debe reservarse SOLO para SQL Server, esto es como DBA 101. El motor no fue diseñado para un entorno de recursos compartidos.
JNK

Respuestas:

12

Es un comportamiento normal para SQL Server asignar tanta memoria como sea posible a su grupo de búferes. Las bases de datos funcionan mejor con mucho buffer. Si desea cambiar el comportamiento, puede establecer la configuración de 'memoria máxima del servidor' . Una buena lectura de fondo sobre eso está aquí.

Matt Whitfield
fuente
1
Con respecto a su edición, el comentario de Aaron es bueno. La razón es que no tiene mucho sentido que un servidor de bases de datos libere memoria. SQL Server responderá a la presión de la memoria y liberará memoria si realmente tiene que hacerlo, pero realmente eso no debería ser necesario.
Matt Whitfield
@MikaJacobi Lo siento, pero tu segunda edición es incorrecta. Desde el punto de vista del desarrollador, entiendo su punto de vista, pero hay una diferencia entre crear un montón de aplicaciones que coexisten y un servicio de servidor que realmente debería ser el único servicio que consume memoria en la máquina. Si desea que SQL Server se comporte como una aplicación "normal", configure la memoria máxima y retírese. Su pregunta era por qué funciona de esta manera, y eso ha sido respondido. Si su pregunta ahora es "bueno, no me gusta que funcione de esa manera", lo siento, pero ya no es una pregunta.
Aaron Bertrand
Lo suficientemente justo. Mi punto de vista es que debería haber una opción para activar o desactivar esto, y la suposición de que el servidor SQL es la única aplicación en un servidor es realmente abusiva (podría ser cierto para las grandes empresas con grandes redes, pero esa no es la única posible o la configuración más común)
Mehdi LAMRANI
Todavía no entiendo por qué necesita SQL Server para liberar la memoria. Si otras aplicaciones lo necesitan, lo recuperarán de SQL Server y SQL Server lo cumplirá. Hasta que esas otras aplicaciones lo necesiten, ¿para qué sirve liberar la memoria?
Aaron Bertrand
1
@AaronBertrand Ok, podría estar equivocado, pero como dije en mi nueva última edición, esto no fue lo que presencié: la memoria no se liberó cuando otra aplicación apenas la necesitaba, causando bloqueos de memoria (de ahí mi insatisfacción ...) De todos modos, vamos cierre el tema, supongo que no hay necesidad real de discutir más que eso.
Mehdi LAMRANI
7

Si realmente desea que el sistema operativo recupere la memoria de SQL Server, tome un gran archivo de 20 GB y cópielo a través de la red. SQL Server liberará la memoria cuando el sistema operativo la necesite. Pero vería una variedad de contadores de rendimiento mientras esto sucede, y vería cómo cambia el rendimiento de su BULK INSERT si lo vuelve a ejecutar mientras se ejecuta la copia o inmediatamente después.

Si desea hacer esto manualmente, debe establecer un límite inferior en la configuración de memoria máxima del servidor SQL Server y reiniciar el servicio. Ahora SQL Server no usará 28GB incluso si lo necesita. Pero esto parece limitar artificialmente SQL Server.

Lo que parece esperar es un comportamiento más flexible, donde puede tener memoria libre parte del tiempo. ¿Con qué propósito? ¿Es esto como reducir un archivo de base de datos para liberar espacio en disco que no puede usar para otros fines porque el archivo de base de datos volverá a crecer?

Es curioso, si escribe una búsqueda en Google de "por qué SQL Server no", el autocompletado más común es "liberar memoria".

Aaron Bertrand
fuente
"Lo que parece esperar es un comportamiento más flexible". Exactamente. Quiero que el servidor SQL use toda la memoria disponible cuando esté disponible, pero cuando terminen estos momentos pesados, volver al estado de "suspensión" y dejar que las otras aplicaciones que necesitan memoria hagan su trabajo cómodamente (puede echar un vistazo a mi nueva última edición sobre este punto)
Mehdi LAMRANI
Para un caso concreto que ilustra por qué necesito hacer esto, puede echar un vistazo a mi último comentario a JNK al final de la pregunta
Mehdi LAMRANI
4

Desafortunadamente, esto es por diseño, por favor consulte esta publicación. Sin embargo, en esta publicación le da algunas instrucciones sobre cómo controlarlo.

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

Asignación de memoria Editar

La memoria no está freedactiva porque asigna memoria de manera muy similar a una aplicación .NET. Dado que la asignación de memoria es costosa, mantendrá esa asignación a menos que el SO lo solicite. Pero, no temas, si el sistema operativo quiere la memoria, la obtendrá, tal como lo hace en una aplicación .NET.

Mike Perrenoud
fuente
@MikaJacobi Claro, no hay problema. Otra cosa a tener en cuenta, para que lo sepas, SQL Server también se hará cargo de todos los núcleos, así que asegúrate de limitar la cantidad de núcleos disponibles. He visto que SQL Server realmente destruye el sistema operativo en el que se ejecuta antes y tuve que reiniciar un centro de datos SQL Server.
Bueno saber. Tengo 24 núcleos, así que está bien por ahora. Pero, ¿por qué no se libera memoria después de que finaliza la inserción masiva?
Siempre que la inserción masiva se haya completado, si el sistema operativo necesita la memoria, se le dará, pero asigna memoria de manera muy similar a una aplicación .NET, de modo que si la necesita y nadie más puede acceder a ella más rápido.
Mi experiencia práctica contradice esto (seel última edición).
Mehdi LAMRANI