2010-02-19 22 views
8

Actualmente estoy teniendo siguiente mensaje de error al ejecutar un archivo .sql con alrededor de 26 MB en SQL Server 2005:SQL Server 2005 Error 701 - sin memoria

Msg 701, Level 17, State 123 
There is insufficient system memory to run this query. 

estoy trabajando con 4 GB de RAM, 64 bits Windows 7 Ultimate, Core2Duo T6400 (2GHz) ...

¿Hay alguna manera de ejecutarlo sin recibir este mensaje (quizás forzar a SQL Server a usar el archivo de intercambio?) O una forma de ejecutarlo en partes (como 100 consultas) un tiempo) ...

El archivo es básicamente un CREATE TABLE seguido de miles de INSER T consultas y tengo muchos de esos (archivos .DBF convertidos a consultas SQL usando convertidor ABC DBF)

¡Cualquier idea será muy apreciada!

Respuesta

9

Esta pregunta parece surgir cada cierto tiempo aquí. Mark tiene la respuesta correcta (y más comúnmente empleada), pero déjame intentar agregar lo que pueda para que quede más claro.

El mensaje de error es un poco engañoso. SQL Server le dice que no tiene memoria suficiente para ejecutar la consulta, pero lo que realmente significa es que no tiene suficiente memoria para analizar la consulta.

Cuando se trata de ejecutando la consulta, SQL Server puede usar todo lo que quiera, gigabytes si es necesario. El análisis es otra historia; el servidor tiene que construir un árbol de análisis sintáctico y solo hay una cantidad muy limitada de memoria disponible para eso. Nunca he encontrado el límite real documentado en ninguna parte excepto para un lote típico lleno de declaraciones INSERT, no puede manejar más de unos pocos MB a la vez.

Así que lamento decirte esto pero no se puede hacer que SQL Server ejecute este script exactamente como está escrito. De ninguna manera, de ninguna manera, no importa qué ajustes modifiques.Usted, sin embargo, tiene una serie de opciones para trabajar alrededor de ella:

Específicamente, usted tiene tres opciones:

  1. Uso GO declaraciones. Esto es utilizado por SSMS y varias otras herramientas como un separador de lotes. En lugar de generar un único árbol de análisis para todo el script, se generan árboles de análisis individuales para cada segmento del lote separados por GO. Esto es lo que hace la mayoría de la gente, y es muy sencillo hacer que el guión sea seguro para las transacciones, como otros han demostrado y no repetiré aquí.

  2. En lugar de generar un script masivo para insertar todas las filas, conserve los datos en un archivo de texto (es decir, separados por comas). Luego impórtelo usando el bcp utility. Si necesita que esto sea "secuencia de comandos", es decir, la importación debe realizarse en la misma secuencia de comandos/transacción que la instrucción CREATE TABLE, utilice el BULK INSERT. Aunque BULK INSERT es una operación no registrada, lo crea o no, todavía se puede colocar dentro de un bloque BEGIN TRAN/COMMIT TRAN.

  3. Si realmente, realmente desea el INSERT a ser una operación registrada, y no quieren las inserciones que sucedan en lotes, a continuación, puede utilizar OPENROWSET para abrir un archivo de texto, archivo de Excel, etc. como una "tabla" ad-hoc, y luego insertar esto en su tabla recién creada. Normalmente soy reacio a recomendar el uso de OPENROWSET, pero como esto es claramente un script administrativo, no es realmente un problema importante.


comentarios anteriores sugieren que se siente incómodo con # 1, a pesar de que sólo puede ser debido a una incorrecta suposición de que no se puede hacer en una sola transacción, en cuyo caso ver Thomas ' s respuesta. Pero si está decidido a seguir de otra manera, le sugiero ir con el n. ° 2, crear un archivo de texto y usar BULK INSERT. Un ejemplo de un guión "seguro" sería:

BEGIN TRAN 

BEGIN TRY 

    CREATE TABLE MyTable (...) 

    BULK INSERT MyTable 
    FROM 'C:\Scripts\Data\MyTableData.txt' 
    WITH (
     FIELDTERMINATOR = ',', 
     ROWTERMINATOR = '\r\n', 
     BATCHSIZE = 1000, 
     MAXERRORS = 1 
    ) 

    COMMIT 

END TRY 

BEGIN CATCH 

    ROLLBACK 

END CATCH 

Esperemos que esto le ayuda a poner en el camino correcto. Estoy bastante seguro de que esto cubre todas las opciones disponibles "en la caja". Más allá de esto, tendrías que empezar a escribir programas de aplicaciones reales o scripts de shell para hacer el trabajo, y no creo que ese nivel de complejidad sea realmente garantizado aquí.

4

Puede dividir el archivo en varios lotes, p. agregar una declaración de ir después de cada mil inserts

por ej.

insert db..table(field list) values ... 
insert db..table(field list) values ... 
go 
insert db..table(field list) values ... 
... 
insert db..table(field list) values ... 
go 

Otra forma puede ser que utilice la carga masiva, p. BCP

+0

Hasta que se edite, significa AGREGAR una instrucción 'GO' después de cada mil insertos. –

+0

Gracias Alex - actualizado como sugerido – Mark

+0

Ya utilicé declaraciones GO para resolver el problema, pero no quiero usar la ejecución por lotes porque si tengo algún error tendré problemas rodando la transacción ... – Tufo

0

Además aspersión declaraciones GO cada tantos registros, si usted está preocupado acerca de todo esto correr o hacer retroceder a continuación, utilizar una transacción de este modo:

SET XACT_ABORT ON 
BEGIN TRAN 

Insert ... 
Insert ... 
Insert ... 
... 
GO 
Insert .. 
Insert .. 
Insert .. 
GO 

If @@TranCount > 0 Commit Tran 

Con XACT_ABORT en ON, cualquier instrucción de inserción que falla revertirá la transacción completa.

-1

Se podría añadir comandos DBCC en medio de las consultas SQL como:

DBCC FREESYSTEMCACHE ('ALL') 
GO 
DBCC FREESESSIONCACHE 
GO 
DBCC FREEPROCCACHE 
GO 

Esto le ayudará a liberar la memoria. Además, Microsoft publica una revisión para solucionar este problema en Sql Server 2005 (mira here). Intenta instalar el Hotfix \ Service Pack.

Cuestiones relacionadas