web-dev-qa-db-fra.com

Comment exécuter un gros script avec de nombreuses insertions sans manquer de mémoire?

Question:

J'ai un script avec environ 45 000 insertions de déclarations sélectionnées. Lorsque j'essaye de l'exécuter, j'obtiens un message d'erreur indiquant que je n'ai plus de mémoire. Comment puis-je exécuter ce script?

Contexte:

  1. Ajout de nouveaux champs de données pour faire jouer une application Nice avec une autre application utilisée par le client.
  2. Vous avez obtenu une feuille de calcul du client pleine de données qui a mappé les éléments de données actuels aux valeurs de ces nouveaux champs.
  3. Feuille de calcul convertie pour insérer des instructions.
  4. Si je n'exécute que certaines des instructions, cela fonctionne, mais pas tout le script.
  5. Non, il n'y a pas de fautes de frappe.

S'il y a une manière différente de charger ces données, n'hésitez pas à me châtier et à me le faire savoir.

28
spaghetticowboy

La taille de lot maximale pour SQL Server 2005 est de 65 536 * taille de paquet réseau (NPS), où NPS est généralement de 4 Ko. Cela équivaut à 256 Mo. Cela signifierait que vos instructions d'insertion seraient en moyenne de 5,8 Ko chacune. Cela ne semble pas juste, mais il y a peut-être des espaces étrangers ou quelque chose d'inhabituel là-dedans.

Ma première suggestion serait de mettre une instruction "GO" après chaque instruction INSERT. Cela divisera votre lot unique de 45 000 instructions INSERT en 45 000 lots distincts. Cela devrait être plus facile à digérer. Soyez prudent, si l'un de ces inserts échoue, vous aurez peut-être du mal à trouver le coupable. Vous voudrez peut-être vous protéger avec une transaction. Vous pouvez ajouter ces instructions rapidement si votre éditeur a une bonne recherche et remplacement (qui vous permettra de rechercher et de remplacer les caractères de retour comme\r\n) ou une fonction de macro.

La deuxième suggestion consiste à utiliser un Wizard pour importer les données directement à partir d'Excel. L'assistant crée un petit package SSIS pour vous, dans les coulisses, puis l'exécute. Il n'aura pas cela problème.

17
darin strait

BULK INSERT ou bcp semblent des options plus appropriées que 45 000 instructions d'insertion.

Si vous devez vous en tenir aux instructions d'insertion, je considérerais quelques options:

R: Utilisez des transactions et encapsulez des lots de 100, 500 ou 1 000 relevés dans chacun pour minimiser l'impact sur le journal et le lot. par exemple.

BEGIN TRANSACTION;
INSERT dbo.table(a, ...) SELECT 1, ...
INSERT dbo.table(a, ...) SELECT 2, ...
...
INSERT dbo.table(a, ...) SELECT 500, ...
COMMIT TRANSACTION;
GO

BEGIN TRANSACTION;
INSERT dbo.table(a, ...) SELECT 1, ...
INSERT dbo.table(a, ...) SELECT 2, ...
...
INSERT dbo.table(a, ...) SELECT 500, ...
COMMIT TRANSACTION;
GO

B: Au lieu d'instructions d'insertion individuelles, utilisez UNION ALL pour 100 ou 500 relevés à la fois, par exemple.

INSERT dbo.table(a, ...)
SELECT 1, ...
UNION ALL SELECT 2, ...
...
UNION ALL SELECT 500, ...
GO

INSERT dbo.table(a, ...)
SELECT 501, ...
UNION ALL SELECT 502, ...
...
UNION ALL SELECT 1000, ...
GO

J'ai laissé la gestion des erreurs par souci de concision, mais le fait est que je n'essaierais jamais d'envoyer un seul lot de 45 000 instructions individuelles à SQL Server.

14
Aaron Bertrand

Je ne sais pas pourquoi vous obtenez l'erreur de mémoire insuffisante, mais il existe une approche plus simple.

Si vous pouvez exporter les données de la feuille de calcul dans un format délimité (par exemple csv), vous pouvez utiliser l'assistant d'importation de données dans SSMS pour insérer les données pour vous:

SSMS import data task.

9
datagod

À l'aide de plusieurs SqlBulkCopy, créez une table temporaire. Insérez de nouvelles données dans la table temporaire, puis fusionnez les données de la table temporaire dans la table existante. Exemple utilisant le C # méthode SqlBulkCopy.WriteToServer (DataTable) . J'espère que cela aide

0
Hung Vu

Oui, nous avons pu le faire, j'ai essayé avec une approche [~ # ~] bcp [~ # ~] (Bulk Copy Program) afin d'éviter un Problème OutOfMemory .

Remarque : essayé sur SQL Server 2014.

Dans BCP, nous devons d'abord exporter les données de la base de données source vers le fichier bcp (dans le dossier du répertoire local), puis nous devons l'importer fichier bcp dans la base de données de destination.

enter image description here

Voici les étapes de la marche du gâteau:

Remarque:

a) Assurez-vous que la table vide est présente dans la base de données de destination

b) Assurez-vous que le dossier Temp est présent dans [~ # ~] c [~ # ~] lecteur

  1. Créez un fichier bat nommé Export_Data.bat avec la commande ci-dessous:

    bcp.exe [Source_DataBase_Name].[dbo].[TableName] OUT "C:\Temp\TableName.bcp" -S "Computer Name" -U "SQL Server UserName" -P "SQL Server Password" -n -q 
    

    pause

  2. Exécutez ce fichier bat, à la suite de quoi un fichier bcp sera généré dans Temp dossier

  3. Créez ensuite un autre fichier bat nommé Import_Data.bat avec la commande suivante:

    bcp.exe [Destination_DataBase_Name].[dbo].[TableName] IN "C:\Temp\TableName.bcp" -S "Computer Name" -U "SQL Server UserName" -P "SQL Server Password" -n -q 
    

    Pause

Et c'est reparti!

0
Kms