Используемая память не освобождается после вставки SQL BULK / экспорта BCP

10

Я создал очень простую таблицу SQL следующим образом

CREATE TABLE [dbo].[TickData](
[Date] [varchar](12) NULL,
[Time] [varchar](12) NOT NULL,
[Symbol] [varchar](12) NOT NULL,
[Side] [varchar](2) NOT NULL,
[Depth] [varchar](2) NOT NULL,
[Quote] [varchar](12) NOT NULL,
[Size] [varchar](18) NOT NULL
    ) ON [PRIMARY]

Затем я выполнил массовую вставку на 3 гигабайта

    BULK
    INSERT TickData
    FROM 
    'C:\SUMO.csv'
    GO

Затем использование оперативной памяти для SQL-сервера стало стремительным, потребляя около 30 ГБ оперативной памяти:

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

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

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

РЕДАКТИРОВАТЬ:
Хорошо, это похоже на поведение по умолчанию. Справедливо.
Тем не менее, почему память не освобождается долго после завершения массовой вставки?

Пара дополнительных соображений:
Что касается комментариев, касающихся SQL-сервера, освобождающего память, когда об этом «сообщает» ОС, то мой практический опыт работы с 24-ядерным 32-гигабайтным сервером Xeon доказывает, что это будет неточно: после завершения извлечения памяти-прожорливого BCP У меня есть пул .Net Экземпляров моего приложения для обработки данных, которые должны обрабатывать извлеченные данные, и они оставляют удушающие / боевые действия, чтобы разделить оставшуюся память, чтобы попытаться выполнить свою работу, что занимает больше времени, чем при включении SQL Server выкл и память доступна для всех приложений, чтобы поделиться. Я должен остановить агент SQL Server, чтобы все прошло гладко и предотвратить сбои приложений для Articiallt, вызвавшего исключение OutOfMemmroy. Что касается искусственного ограничения / ограничения жестокой памяти, если доступна свободная память, почему бы не использовать его? В идеале это было бы динамически настроено на адаптацию к тому, что доступно, а не просто насильственное ограничение «случайным образом». Но я предполагаю, что это не совсем так, поэтому дело закрыто по этому последнему пункту.

Мехди ЛАМРАНИ
источник
6
Почему SQL Server должен освободить память? Если для выполнения этой операции ему понадобилась память, она понадобится снова. Если бы SQL Server освободил память, для чего бы вы ее использовали? Почему память должна быть свободной? Если вы используете память для чего-то другого, то эта массовая вставка запускается снова, что должно произойти?
Аарон Бертран
Единственное действие, которое вы можете предпринять, чтобы избежать этого, - установить максимальный объем памяти. Чтобы «восстановить» память, вы можете перезапустить службу SQL Server. Очевидно, что это освободит память, и когда служба перезапустится, она выделит память нормально.
TMN
Я убрал последнее редактирование. Если вы хотите поспорить / обсудить достоинства или проблемы кодирования SQL Server (или любого другого механизма БД), найдите лучшее место для этого. На оригинальный вопрос ответили, по-видимому, правильно и достаточно. Если этот Q продолжает ползти, он может быть заблокирован.
JNK
Нет ничего плохого в том, чтобы знать ответы и обсуждать методологии, только не здесь, на сайте вопросов и ответов. Вы можете определенно провести это обсуждение в чате или на форуме, но Stack Exchange немного более структурирован, и вопросы для обсуждения будут закрыты очень быстро.
JNK
3
Кроме того, мне, как не модератору, интересно, почему вы запускаете на своем сервере не-SQL-компоненты? Поле должно быть зарезервировано JUST для SQL Server, это похоже на DBA 101. Механизм не предназначен для среды с общими ресурсами.
JNK

Ответы:

12

SQL Server обычно выделяет столько памяти, сколько может, в свой буферный пул. Базы данных лучше всего работают с большим количеством буфера. Если вы хотите изменить поведение, вы можете установить параметр «max server memory» . Хорошая справочная информация об этом здесь.

Мэтт Уитфилд
источник
1
Что касается вашей правки, комментарий Аарона - хороший. Причина в том, что в сервере баз данных мало смысла освобождать память. SQL Server будет реагировать на нехватку памяти и освобождать память, если это действительно необходимо, но на самом деле в этом нет необходимости.
Мэтт Уитфилд
@MikaJacobi Извините, но ваше второе редактирование неверно. С точки зрения разработчика, я понимаю вашу точку зрения, но есть разница между созданием нескольких приложений, которые сосуществуют, и серверной службой, которая действительно должна быть единственной службой, потребляющей память на машине. Если вы хотите, чтобы SQL Server вел себя как «нормальное» приложение, установите максимальный объем памяти и уходите. Ваш вопрос был, почему это работает таким образом, и на него был дан ответ. Если ваш вопрос сейчас «ну, мне не нравится, что так работает» - извините, но это уже не вопрос.
Аарон Бертран
Справедливо. Моя точка зрения заключается в том, что должна быть возможность включить или выключить это, и предположение, что SQL-сервер является единственным приложением на сервере, действительно оскорбительно (может быть верно для больших компаний с большими сетями, но это не единственное возможно ни самая распространенная настройка)
Мехди ЛАМРАНИ
Я до сих пор не понимаю, зачем вам SQL Server для освобождения памяти. Если это понадобится другим приложениям, они заберут его с SQL Server, и SQL Server выполнит его. До тех пор, пока это не понадобится другим приложениям, какова цель освобождения памяти?
Аарон Бертран
1
@AaronBertrand Хорошо, я могу ошибаться, но, как указано в моем новом последнем редактировании, это не то, что я засвидетельствовал: память не освобождалась, когда другое приложение нуждалось в этом, вызывая сбои памяти (отсюда мое недовольство ...). закройте тему, я думаю, что нет необходимости спорить больше, чем это.
Мехди ЛАМРАНИ
7

Если вы действительно хотите, чтобы ОС забрала память у SQL Server, возьмите большой файл размером 20 ГБ и скопируйте его по сети. SQL Server освободит память по мере необходимости ОС. Но я бы посмотрел различные счетчики производительности, пока это происходит, и посмотрел бы, как изменится производительность вашего BULK INSERT, если вы запустите его снова либо во время копирования, либо сразу после него.

Если вы хотите сделать это вручную, то вам следует установить нижний предел на максимальный объем памяти сервера SQL Server и перезапустить службу. Теперь SQL Server не будет использовать 28 ГБ, даже если ему это нужно. Но это, кажется, искусственно ограничивает SQL Server.

Вы, кажется, ожидаете более гибкого поведения, когда у вас может быть свободная часть времени. Для чего? Это похоже на сжатие файла базы данных, чтобы освободить место на диске, которое вы не можете использовать для других целей, потому что файл базы данных снова будет расти?

Забавно, если вы набираете в поиске Google слово «почему нет SQL Server», то наиболее распространенным автозаполнением является «освобождение памяти».

Аарон Бертран
источник
1
Также см. Serverfault.com/questions/1279/… и dba.stackexchange.com/questions/6691/…
Аарон Бертран
«То, что вы ожидаете, это более гибкое поведение». В точку. Я хочу, чтобы SQL-сервер использовал всю доступную память, когда она доступна, но когда эти тяжелые моменты прошли, вернитесь в состояние «сна» и оставьте другие приложения, требующие памяти, выполнять свою работу комфортно (вы можете взглянуть на мой новое последнее редактирование по этому вопросу)
Мехди ЛАМРАНИ
Для конкретного случая, иллюстрирующего, почему мне нужно это сделать, вы можете посмотреть @ мой последний комментарий JNK внизу вопроса
Мехди ЛАМРАНИ
4

Это, к сожалению, дизайн, пожалуйста, ссылку на этот пост. Тем не менее, в этом посте он дает вам некоторые инструкции о том, как его контролировать.

/server/251832/sql-server-bulk-insert-physical-memory-issue

Распределение памяти Править

Память не freedработает, потому что она выделяет память во многом как приложение .NET. Поскольку выделение памяти является дорогостоящим, оно будет сохраняться до тех пор, пока ОС не запросит его. Но не бойтесь, если ОС хочет память, она ее получит, как в приложении .NET.

Майк Перренуд
источник
@MikaJacobi Конечно, нет проблем. Еще одна вещь, которую стоит отметить, чтобы вы знали, что SQL Server будет также охватывать все ядра, поэтому убедитесь, что вы ограничиваете количество доступных ядер. Я видел, как SQL Server фактически разрушал операционную систему, на которой он работал раньше, и мне пришлось сильно перезагрузить центр обработки данных SQL Server.
Хорошо знать. У меня 24 ядра, так что пока все в порядке. Но почему память не освобождается после окончания массовой вставки?
Пока массовая вставка завершена, если операционная система нуждается в памяти, она будет ей выделена, но она выделяет память во многом как приложение .NET, так что, если она нужна, и никто другой не делает, она может получить к ней доступ быстрее.
Мой опыт работы противоречит этому (см. Последнее редактирование).
Мехди ЛАМРАНИ