Каковы варианты решения проблемы нехватки памяти при запуске большого пакета вставок? - PullRequest
4 голосов
/ 10 февраля 2012

Я пытаюсь запустить большой пакет операторов вставки (около 30 мегабайт), сгенерированных для повторной синхронизации одной базы данных в соответствии с другой. Я использую 64-разрядную версию SQL Server 2008 R2 на компьютере с Win 7 и 8 гигабайтами памяти.

Когда я запускаю запрос в SSMS, я получаю «Запрос выполнен с ошибками» и не выводится сообщение. После некоторого возни с попытками запустить его вне SSMS я понял, что это ошибка нехватки памяти. На самом деле, даже после ошибок я обнаружил, что служба SQL Server использует около 5,5 гигабайт памяти!

Есть ли параметр, который я могу настроить, который позволит SQL запускать это? Альтернативой является написание программы, которая разбивает запрос на пакеты и запускает их. Интересно, что это, кажется, происходит только с большими запросами, которые содержат вставки. Большие запросы, содержащие обновления, похоже, работают нормально. Возможно, это связано с тем, как они записываются в журнал транзакций. Однако запрос выводится в виде последовательности из множества вставок, и это нельзя изменить.

В любом случае, есть ли параметр в SQL Server, который я могу изменить, чтобы это исправить? Буду признателен за любой совет, который может дать каждый.

Редактировать: Спасибо за ваш ответ, bluefooted. У меня и моего коллеги было такое же впечатление, когда мы впервые увидели ошибку без сообщений - казалось, что SSMS не хватает памяти. Однако, при дальнейшей проверке, похоже, что это SQL Server. Позволь мне объяснить. Мы используем SQL Comparison SDK от Red Gate с Visual Studio для генерации разностных запросов, а затем условно выполняем определенные операторы для объединения двух баз данных в соответствии с определенными правилами. Таким образом, после возникновения этой проблемы мы использовали включенный объект Executor для запуска скрипта. Мы получили следующую ошибку:

System.Data.SqlClient.SqlException occurred
  Message=There is insufficient system memory in resource pool 'internal' to run this query.
  Source=.Net SqlClient Data Provider
  ErrorCode=-2146232060
  Class=17
  LineNumber=79180
  Number=701
  Procedure=""
  Server=QA1
  State=123
  StackTrace:
       at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
       at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
       at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
       at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
       at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async)
       at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)
       at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
       at RedGate.Shared.SQL.ExecutionBlock.BlockExecutor.ExecuteBlock(ExecutionBlock block, String server, String database, Boolean integratedSecurity, String userName, String password)
       at IO.Practiceware.DbSync.Csharp.Program.RunScript(String path, String server, String database)
  InnerException: 

Я не знаю, что из этого можно сделать, но мой более знающий коллега сказал, что это в основном означает, что самому SQL Server не хватает памяти. Буду признателен за любые ваши идеи в этом.

1 Ответ

2 голосов
/ 11 февраля 2012

Несколько идей:

Попробуйте разбить вставки на партии. Каждые 1000 строк или около того вставьте что-то вроде:

INSERT ...
INSERT ...
INSERT ...

GO

INSERT ...
INSERT ...
INSERT ...

Может также не помешать иногда выпускать CHECKPOINT, чтобы уменьшить влияние на журнал.

Вместо отправки тысяч отдельных операторов вставки попробуйте их объединить. Вы можете сделать это несколькими способами, пару примеров:

INSERT dbo.table(col1,col2) SELECT 1,2
UNION ALL SELECT 2,2
UNION ALL SELECT 3,2;

-- or    

INSERT dbo.table(col1,col2)
VALUES(1,2),(2,2),(3,2);

Кроме того, вы можете хранить данные (а не команды вставки) в текстовом файле и использовать BULK INSERT, bcp и т. Д. Вместо обычных вставок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...