2010-02-19 11 views
8

Attualmente sto avendo seguente messaggio di errore durante l'esecuzione di un file sql con circa 26MB su SQL Server 2005:SQL Server 2005 Error 701 - dalla memoria

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

sto lavorando con 4GB di RAM, 64 Bit Windows 7 Ultimate, Core2Duo T6400 (2GHz) ...

C'è un modo per eseguirlo senza ricevere questo messaggio (forse forza SQL Server per utilizzare il file di scambio?) O un modo per eseguirlo in parti (come 100 query un momento) ...

Il file è fondamentalmente un CREATE TABLE seguito da thousads di INSER T query e ho un sacco di quelli (convertiti i file .DBF alle query SQL utilizzando ABC DBF Converter)

Qualsiasi idea sarà molto apprezzata!

risposta

9

Questa domanda sembra davvero venire ogni tanto qui. Mark ha la risposta corretta (e più comunemente utilizzata), ma lascia che provi ad aggiungere ciò che posso per renderlo più chiaro.

Il messaggio di errore è leggermente fuorviante. SQL Server indica che non ha memoria sufficiente per eseguire la query, ma cosa significa in realtà è che non ha memoria sufficiente per parsing la query.

Quando si tratta di in esecuzione la query, SQL Server può utilizzare tutto ciò che desidera - gigabyte se necessario. L'analisi è un'altra storia; il server deve costruire un albero di analisi e c'è solo una quantità molto limitata di memoria disponibile per quello. Non ho mai trovato il limite effettivo documentato da nessuna parte, ma per un tipico lotto pieno di dichiarazioni INSERT, non può gestire più di pochi MB alla volta.

Quindi, mi spiace dirti questo ma tu non puoi rendere SQL Server eseguire questo script esattamente come è scritto. Assolutamente no, non importa quali impostazioni modifichi.Tu, invece, dispone di una serie di opzioni per lavorare intorno ad esso:

In particolare, sono disponibili tre opzioni:

  1. Usa GO dichiarazioni. Questo è usato da SSMS e vari altri strumenti come un separatore di lotti. Invece di un singolo albero di analisi generato per l'intero script, vengono generati alberi di analisi individuali per ogni segmento del batch separati da GO. Questo è quello che fa la maggior parte delle persone, ed è molto semplice rendere lo script transazionale sicuro, come altri hanno dimostrato e non ripeterò qui.

  2. Invece di generare un enorme script per inserire tutte le righe, mantenere i dati in un file di testo (cioè separati da virgola). Quindi importarlo utilizzando bcp utility. Se è necessario che questo sia "scriptable", vale a dire che l'importazione deve avvenire nello stesso script/transazione dell'istruzione CREATE TABLE, quindi utilizzare BULK INSERT. Anche se BULK INSERT è un'operazione non registrata, che ci crediate o meno, è comunque possibile inserirla all'interno di un blocco BEGIN TRAN/COMMIT TRAN.

  3. Se davvero, vuole veramente il INSERT di essere un'operazione registrata, e non vogliono le inserzioni per accadere in batch, quindi è possibile utilizzare OPENROWSET per aprire un file di testo, file excel, ecc come "tabella" ad-hoc, quindi inserirla nella tabella appena creata. Normalmente sono riluttante a raccomandare l'uso di OPENROWSET, ma poiché questo è chiaramente uno script amministrativo, non è davvero un grosso problema.


commenti precedenti suggeriscono che sei a disagio con # 1, anche se questo può essere solo a causa di un presupposto errato che non può essere fatto in una singola transazione, nel qual caso vedi Thomas ' risposta. Ma se sei morto per andare in un altro modo, ti suggerisco di andare con # 2, creando un file di testo e usando BULK INSERT. Un esempio di script "sicuro" sarebbe:

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 

Speriamo che questo ti aiuti a metterti sulla giusta strada. Sono abbastanza sicuro che questo copra tutte le opzioni disponibili "nella scatola" - oltre a queste, dovresti iniziare a scrivere programmi applicativi o script di shell per fare il lavoro, e non penso che quel livello di complessità sia davvero giustificato qui.

4

È possibile suddividere il file in diversi lotti, ad es. aggiungendo una dichiarazione go ogni mille inserti

ad es.

Un altro modo potrebbe essere l'utilizzo del caricamento collettivo, ad es. BCP

+0

Fino a quando non viene modificato, significa AGGIUNGERE una dichiarazione 'GO' dopo ogni mille inserti. –

+0

Grazie Alex - aggiornato come suggerito – Mark

+0

Ho già utilizzato le istruzioni GO per risolvere il problema, ma non voglio utilizzare l'esecuzione in batch perché se ho qualche errore avrò problemi nella transazione di rollbacking ... – Tufo

0

Inoltre aspersione dichiarazioni GO ogni tanti record, se siete preoccupati per il tutto in esecuzione o rollback quindi utilizzare una transazione in questo modo:

SET XACT_ABORT ON 
BEGIN TRAN 

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

If @@TranCount > 0 Commit Tran 

Con XACT_ABORT impostata su ON, qualsiasi dichiarazione dell'inserto che fallisce, ripristinerà l'intera transazione.

-1

Si potrebbe aggiungere comandi DBCC tra le query SQL come:

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

Ciò contribuirà a liberare la memoria. Inoltre, Microsoft rilascia un hotfix per risolvere questo problema in Sql Server 2005 (Look here). Prova a installare l'hotfix \ service pack.

Problemi correlati