Увеличение оперативной памяти, ухудшение производительности

9

Настроить:

  • Windows Server 2008 R2
  • SQL Server 2008 R2 с пакетом обновления 1
  • 240 ГБ ОЗУ
  • TempDB - это файлы данных 8x16 ГБ без автоматического увеличения (всего 128 ГБ)
  • Физический / Автономный Сервер

Этот сервер используется для обработки ETL. Мы только что установили больше оперативной памяти на этом сервере в общей сложности 240 ГБ ОЗУ. Службы SQL Server - единственные действующие вещи.

Память хорошо отображается в BIOS, OpenManage и Windows.

Если я настрою SQL Server на использование минимального / максимального объема памяти 70/100 ГБ, у нас не возникнет проблем. Однако, когда я увеличиваю это значение до 120/150 ГБ, я получаю следующую ошибку при запуске одного из наших процессов ETL:

Не удалось выделить место для объекта «<временный системный объект: 422234507706368>» в базе данных «tempdb», поскольку файловая группа «PRIMARY» заполнена. Создайте дисковое пространство, удаляя ненужные файлы, удаляя объекты в файловой группе, добавляя дополнительные файлы в файловую группу или устанавливая автоматический рост для существующих файлов в файловой группе. (Сообщение 1105, состояние 2, процедура неизвестна, строка 1)

Мы никогда не сталкивались с этой проблемой до изменения конфигурации памяти. После перенастройки обратно на исходные 70 / 100ГБ мы не получаем эту ошибку.

Вещи, которые я пробовал:

  1. Установите файлы данных TempDB для автоматического увеличения. Это просто приводит к автоматическому росту файлов до тех пор, пока не будет достигнута емкость диска, а затем происходит сбой.
  2. Добавьте больше файлов данных TempDB. Та же ошибка, что и на рисунке.
  3. Увеличьте размер TempDB до 8x32 ГБ (всего 256 ГБ)

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

Дерек Кромм
источник
2
Ваша память сбалансирована между узлами NUMA? Как насчет ваших процессоров? Показывает ли журнал SQL Server, сколько процессоров используется во время запуска?
Аарон Бертран
1
Что вы используете для процессов ETL? SSIS или похожий инструмент? Если это инструмент вне SQL Server, запускаете ли вы его на том же сервере, что и ваш экземпляр SQL Server?
Майк Фал
1
Это хороший момент @Mike, если процесс ETL не может захватить достаточно памяти, чтобы выполнить свою задачу, потому что SQL Server использует слишком много, тогда ему, возможно, придется перенести работу в базу данных tempdb.
Аарон Бертран
1
Вот хороший старт для мониторинга использования базы данных tempdb: msdn.microsoft.com/en-us/library/ms176029(v=SQL.105).aspx . Это должно дать вам представление о том, что происходит.
Томас Стрингер,
2
Делали ли вы какой-либо анализ того, что на самом деле работает, когда вы расширяете TempDB? Простой sp_who2 / sp_whoisactive? Для меня это звучит так, будто у вас есть несколько длительных транзакций, которыми можно было бы лучше управлять, но трудно сказать. Лично я бы не стал привязываться к изменению памяти, но сначала посмотрю на код и посмотрим, работает ли он правильно.
Майк Фал

Ответы:

3

Спасибо всем за вашу помощь.

После пролистывания некоторых планов выполнения выясняется, что существует JOIN, который обрабатывается по-разному в зависимости от объема доступной оперативной памяти. С меньшим количеством оперативной памяти он оценивает его с помощью хэша; с большей оперативной памятью используется серия Merge Joins.

Так что в основном все сводилось к плохо написанному T-SQL, который я в настоящее время занимаюсь рефакторингом.

Дерек Кромм
источник
4
Это довольно противоречиво, потому что хеш-соединение требует предоставления памяти, а слияние - нет. Существует ли дополнительная операция сортировки для поддержки объединения слиянием?
Мартин Смит
1

Это не ответ на вопрос, просто код, который я не хотел публиковать в комментарии. Чтобы увидеть баланс ваших планировщиков и памяти между узлами NUMA (а также увидеть, не видны ли какие-либо узлы в сети):

SELECT 
  parent_node_id, 
  [status],
  AVG(current_tasks_count) AS avg_tasks_count, 
  AVG(load_factor) AS avg_load_factor,
  scheduler_count = COUNT(*)
FROM sys.dm_os_schedulers
GROUP BY parent_node_id, [status];

SELECT 
  memory_node_id, 
  name, 
  SUM(single_pages_kb + multi_pages_kb) AS memory_kb
FROM sys.dm_os_memory_clerks
GROUP BY memory_node_id, name;

(В SQL Server 2012 последнее SUMдолжно быть последним, SUM(pages_kb)поскольку больше нет отдельных одно- и многостраничных распределителей.)

Аарон Бертран
источник