Як запустити великий сценарій з багатьма вставками, не втрачаючи пам'яті?


28

Питання:

У мене є сценарій із близько 45 тис. Вкладишів із вибраних висловлювань. Коли я намагаюся запустити його, я отримую повідомлення про помилку, в якому зазначається, що у мене закінчилося пам’ять. Як я можу запустити цей сценарій для запуску?

Контекст:

  1. Додано кілька нових полів даних, щоб зробити додаток гарним для гри з іншим додатком, який використовує клієнт.
  2. Отримав електронну таблицю даних від клієнта, повна даних, які відобразили поточні елементи даних у значення для цих нових полів.
  3. Перетворена електронна таблиця для вставки операторів.
  4. Якщо я запускаю лише деякі твердження, це працює, але весь сценарій цього не робить.
  5. Ні. Немає помилок.

Якщо є інший спосіб, я повинен завантажувати ці дані, сміливо каріть мене і повідомте мене.


Аналогічне запитання щодо SO: ( stackoverflow.com/questions/222442/… ) Не впевнений, чи допоможе відповідь
jumpdart

Відповіді:


17

Максимальний розмір партії для SQL Server 2005 становить 65536 * Розмір мережевого пакету (NPS), де NPS зазвичай становить 4 КБ. Це працює на 256 МБ. Це означає, що ваші вкладені висловлювання становитимуть в середньому 5,8 КБ кожен. Це не здається правильним, але, можливо, там є сторонні простори або щось незвичне.

Першою моєю пропозицією було б ставити заяву "GO" після кожного заяви INSERT. Це розбиває вашу одну партію з 45 000 заяв про INSERT на 45 000 окремих партій. Це має бути легше перетравлюватися. Будьте обережні, якщо одна з цих вставок виходить з ладу, можливо, вам буде важко знайти винуватця. Ви можете захистити себе транзакцією. Ви можете швидко додати ці висловлювання, якщо ваш редактор має хороший пошук і заміна (що дозволить вам шукати і замінювати символи, що повертаються, такі як \ r \ n) або засоби макросу.

Друга пропозиція - використовувати Майстер для імпорту даних безпосередньо з Excel. Майстер будує для вас невеликий пакет SSIS поза кадром, а потім виконує це. У неї не буде цієї проблеми.


2
А GOпісля кожного твердження? Я думаю, якщо ви їх генеруєте, використовуючи інший сценарій, це нормально. В іншому випадку я просто ставлю один раз через кожні 1000 INSERTс. Що стосується того, щоб зробити транзакцію атомною та звести до мінімуму розмір транзакції, чому б не завантажувати всі рядки в змінну темп або таблицю та не завантажувати їх в один кадр звідти до цільової таблиці?
Нік Чаммас

1000 так само добре, як 1, але важче підрахувати. Якщо чесно, він може піти лише з одним заявою GO, на півдорозі, біля заяви 21 500. Мені подобається виправлення GO, оскільки воно не потребує складного редагування поточного сценарію або підрахунку виписок INSERT (які можуть не відображатися безпосередньо на номери рядків).
протока Дарина

2
Безумовно, навіть погане наближення 1000 тверджень досить добре. :)
Нік Чаммас

1
Додавання GO було швидким та простим виправленням. Сценарій 25 Мб працює трохи менше ніж за 9 хвилин без проблем. Хотіли мати його як сценарій, щоб він міг зберігати його в стандартному процесі розгортання патчів, коли він вийде.
spaghetticowboy

14

BULK INSERTабо bcpздаються більш підходящими варіантами, ніж 45 000 вкладених операторів.

Якщо вам потрібно дотримуватися заяви про вставку, я б розглядав кілька варіантів:

Відповідь: Використовуйте транзакції та загортайте партії з 100 або 500 або 1000 висловлювань у кожному, щоб мінімізувати вплив на журнал та пакет. напр

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

В: Замість окремих операторів вставки, використовуйте UNION ALLодночасно 100 або 500 заяв, наприклад

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

У мене залишилося вирішення помилок для стислості, але справа в тому, що я ніколи не намагався б надіслати жодну партію з 45 000 окремих заяв на SQL Server.


1
Шкода, що ОП не може використовувати конструктори табличних значень , функцію 2008+. Йому все одно доведеться згрупувати вставки в групи з 1000 рядків, що є максимумом, який ви можете згрупувати разом з TVC.
Нік Шамма

Це було моєю першою пропозицією, поки я не побачив тег версії.
Аарон Бертран

2
@ NickChammas - Продуктивність цих функцій погіршується нелінійно з кількістю значень BTW . Я подав елемент підключення із запитом про вставку 1000 рядків з 10 VARCHAR(800)стовпцями 2008 року з часом складання 12,5 хвилин на моєму екземплярі 2008 Dev, оскільки це робить багато непотрібних робіт, порівнюючи значення, а не просто вступаючи з їх вставленням (виконує багато швидше, коли параметризовано та немає значень для перегляду). Хоча сильно покращився у 2012 році, нелінійний малюнок все ще існує і має бути виправлений у версії після.
Мартін Сміт

9

Я не впевнений, чому ви вибуваєте з помилки пам’яті, але є простіший підхід.

Якщо ви можете експортувати дані з електронної таблиці в обмежений формат (наприклад, csv), ви можете використовувати майстер імпорту даних у SSMS, щоб вставити дані для вас:

Завдання імпорту даних SSMS.


це корисно, але я не маю доступу до баз даних клієнтів. Мені потрібно підготувати виправлення та завантаження даних у сценаріях
spaghetticowboy

0

За допомогою декількох SqlBulkCopy створіть таблицю темпів. Вставте нові дані в таблицю темп, а потім об'єднайте їх у таблицю темп із вже наявними. Приклад з використанням методу C # SqlBulkCopy.WriteToServer (DataTable) . Сподіваюся, це допомагає


0

Так, ми могли б це зробити, я намагався застосовувати підхід BCP (Bulk Copy Program), щоб уникнути проблеми OutOfMemory .

Примітка : Пробували на SQL Server 2014.

У BCP спочатку нам потрібно експортувати дані джерельної бази у файл bcp (у папку локального каталогу), а потім потрібно імпортувати цей bcp файл до бази даних призначення.

введіть тут опис зображення

Нижче наведено кроки прогулянки по тортах:

Примітка:

a) Переконайтеся, що порожня таблиця присутня в базі даних призначення

b) Переконайтесь, що папка Temp присутня на диску C

  1. Створіть файл bat з назвою Export_Data.bat за допомогою команди, показаної нижче:

    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 

    пауза

  2. Запустіть цей bat файл, в результаті чого в папці Temp буде генеруватися bcp- файл

  3. Потім створіть інший файл bat з ім'ям Import_Data.bat за допомогою наступної команди:

    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 

    Пауза

А ось і ми!


Помилка отримання "Дійсне ім'я таблиці потрібне для параметрів в, виходу або формату." при спробі експорту даних.
Сена Якова

1
Ви можете вставити команду, яку ви пробували, зі всім значенням атрибута. Дотримуйтесь наведеного нижче прикладу: bcp.exe ExportDB.dbo.AddressCountry OUT "C: \ Temp \ AddressCountry.bcp" -S "IN-L20054" -U "sa" -P "sa" -n -q У тому, що [ExportDB -> вихідний БД, AddressCountry-> таблиця, присутня у вихідному БД, IN-L20054 -> Ім'я машини, "sa" - це ім'я користувача / pwd БД]
Кмс

Зараз я цього не маю. Я в кінцевому рахунку використовував функцію імпорту даних у SSMS. Потім підключили цільову БД (v14.0) до вихідної БД (v.15.0) за допомогою підключення MS OLE DB, і було досить швидко імпортувати багатомільйонні рядки даних. Спасибі!
Сена Якова
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.