Материал посвящен описанию использования подсистемы памяти в MS SQL server. Данный обзор дает только общее представление о структуре управления. Следует помнить, что продукты компании Microsoft поставляются с закрытыми кодами и детальные сведения отсутствуют в общедоступных источниках (насколько удалось выяснить нам, если Вам удалось большее – сообщите, пожалуйста). Общий обзор необходим для понимания описываемых далее возможных проблем SQL server и используемых средств тестирования и измерения производительности.
Memory manager
Memory manager (ММ) является основным элементом, который управляет распределением памяти в SQL сервере. Данный компонент автоматически распределяет доступную SQL серверу память, снижая необходимость ручной настройки. После загрузки SQL ММ определяет первоначальный объем распределенной памяти и далее по мере изменения нагрузки динамически резервирует или освобождает оперативную память. Таким образом, ММ управляет взаимодействием SQL сервера с операционной системы в контексте управления памятью. Memory manager является частью SQLOS. Подробнее можно посмотреть здесь.
Состав Memory Manager
Сведения о составе этого компонента весьма ограничены, однако можно выделить следующие составные части ММ: memory nodes, memory clerks (клерки памяти), memory caches (кэши) и memory objects (объекты). Подробнее можно прочитать здесь и здесь.
Также ММ предоставляет несколько счетчиков, которые позволяют оценить использование оперативной памяти в SQL. Подробнее можно прочитать здесь и здесь.
Обобщенно состав ММ представлен на Рисунке 1.1
Рисунок 1.1 Компоненты Memory Manager
Объекты ММ используются для распределения памяти внутри экземпляра SQL Server. Memory nodes обеспечивают интерфейс к ОС и реализацию выделения памяти на нижнем уровне. Внутри SQL Server только Memory clerks имеют доступ к интерфейсу. Memory nodes для распределения памяти. Каждый компонент SQL Sever, который потребляет существенный объем памяти должен создать собственный клерк и распределять память именно через его интерфейс.
Реализация управлению памятью меняется от версии к версии SQL, однако основные функциональные компоненты сохраняются. На рисунке 2.2 приведены отличия в реализации ММ в SQL2008 и SQL2012 дополнительные сведения можно найти здесь.
Рисунок 1.2 Изменения в структуре Memory Manager для SQL2008 и SQL 2012
Из рисунков видно, что полностью исчезло разделение page allocator. Эти компоненты были заменены одним Any-size page allocator.
Memory Nodes
Memory Nodes является внутренним объектом SQLOS. Представляет собой логический объект памяти, которая соответствует процессору в случае SMP-реализации или группе процессоров в случае NUMA-реализации. Подробнее можно посмотреть здесь.
Рисунок 1.3 Иерархия SQLOS в случае реализации SMP (А — рисунок) и NUMA (Б- рисунок)
Memory node абсолютно прозрачна для потребителей памяти. Главная задача этого компонента состоит в определении области выделения памяти. Memory node состоит из нескольких распределителей памяти (memory allocators). На рисунке 2.4 представлены потребители памяти, использующие memory node. Подробнее можно посмотреть здесь и здесь.
Рисунок 1.4 Memory nodes
Memory allocators являются процедурами, которые определяют тип Windows API используемой для выделения памяти. Аллокаторы содержат программный код используемый для выделения памяти, например, для страниц или использования shared memory.
Memory clerks
Memory nodes обеспечивают интерфейс к ОС и реализацию выделения памяти на уровне Windows. Внутри SQL Server только Memory clerks имеют доступ к интерфейсу Memory nodes для распределения памяти. Каждый компонент SQL Sever, который потребляет существенный объем памяти, должен создать собственный клерк и далее распределять ресурсы именно через его интерфейс.
Таким образом, клерки выполняют следующие функции в рамках Memory manager:
• Отражают использование памяти конкретными компонентами сервера
• Получают уведомления о смене состояний памяти и изменяют её размер согласно обстоятельствам.
• Используют Memory nodes для выделения памяти компонентам сервера.
Выделяют четыре категории клерков. Список категорий приведен в таблице 1. Подробнее можно посмотреть здесь.
Memory Caches
Под понятием «кэш» понимается механизм кэширования различных типов данных с учетом стоимости хранения объектов. Кэш обеспечивает: контроль времени хранения, видимость и анализ статистики обращения к кэшированным данным. Кэшированные данные могут быть использованы одновременно несколькими потребителями. Кроме кэшей SQL Server использует пулы памяти. Пулы в отличии от кэшей используются для хранения однородных данных без дополнительного контроля. Используется несколько механизмов кэширования и них основные:
• Cache Store
• User Store
• Object Store
Только Object Store является пулом, Cache и Object Store являются кэшами. Механизмы Cache и User Store весьма похожи, однако если параметры Cache Store контролируются целиком SQLOS, то для User Store разработчики могут использовать собственные алгоритмы управления. В документации также используются понятия Cache Store и User Store со значением “обособленные области памяти”. Каждому Cache Store сопоставлено хранилище hash table. Возможно использование не одной, а нескольких таблиц hash tables.
Подробнее можно прочитать здесь и здесь и здесь.
Cache Store используются, например, для хранения кэша планов выполнения, кэша xml, кэша полнотекстового поиска, Procedure Cache, System Rowset Cache. В User Store хранятся в частности кэш метаданных пользовательских и системных баз, токены безопасности, данные схем. Полный список можно найти в динамическом представлении dm_os_memory_cache_counters.
Buffer pool (buffer cache) а также buffer pool extension
Buffer pool (второе название buffer cache) – это область в памяти, которая используется для кэширования страниц, данных таблиц и их индексов, размер страниц 8Кб. Использования Buffer pool уменьшает ввод/вывод в файл базы данных и таким образом увеличивает производительность сервера. При этом Buffer Cach является основным потребителем памяти в SQL Server.
Рисунок 1.5 Компоненты системы управления буфером
В SQL Server 2014 buffer pool может быть расширен в энергонезависимую память, например, на диск SSD. Такое расширение называется Buffer Pool Extension. Подробнее можно прочитать здесь здесь.
Подробнее об управлении буферным кэшем можно прочитать здесь, здесь и здесь.
Буферный кэш имеет собственный клерк памяти и распределят память через page allocator. Для буферного кэша используется клерк памяти типа Generic и называется memoryclerk_sqlbufferpool.
До SQL 2012 Buffer Cache использовал только Single Page Allocator (распределяющий отдельные страницы 8Кб). Если компоненту сервера было необходимо выделить буфер большего, чем 8Кб размера использовался Multi Page Allocator (см. рис. 2.4) и соответственно эта память располагалась за пределами Buffer Pool. C SQL2012 Single и Multi Page allocators были объединены в Any-size page allocator. На рис. 2.2 можно увидеть эти изменения.
Max server memory и min server memory
Хотя управление буферным кэшем происходит автоматически внутри SQL Server, однако администраторы могут регулировать максимальный и минимальный размер распределяемой памяти для этого буфера.
Рисунок 1.6 Изменения в диапазоне памяти резервируемой параметром Max server memory
Как уже упоминалось в SQL 2012 произошли изменения memory manager. В результате таких изменений параметр max server memory регулирует не только память buffer pool, но вообще всё распределение памяти (кроме Direct Memory Allocations производимых с помощью VirtualAlloc).
Параметр min server memory обозначает границу, ниже которой Buffer Pool не будет по требованию освобождать занятую память. При первоначальной загрузке пул не занимает память, указанную в min server memory. Используется минимально необходимый объем, который вычисляется автоматически. Размер пула при необходимости в дальнейшем увеличивается.
Подробнее можно прочитать здесь и здесь.
Stolen pages
Stolen pages — это страницы буферного кэша, которые используются для различных целей в сервере. Например, для процедурного кэша, операций сортировки (т.е. рабочей памяти запроса — workplace memory). Также эти страницы необходимы для хранения таких структур данных, которые требуют распределение памяти менее 8Кб, например, блокировки, контекст транзакций и информации о соединении.
Подробнее можно посмотреть в следующих источниках:
simple-talk.com;
technet.microsoft.com;
sqlserver-dba.com.
Object Store
Object Store представляет собой пул памяти. Он используется для хранения однородных типов данных без дополнительного контроля стоимости хранения. Эти данные могут быть легко очищены в случае нехватки памяти. По своей структуре пулы являются клерками памяти (т.е. являются одним из его видов). Дополнительно можно посмотреть здесь и здесь.
Memory Objects (MO)
Memory Objects представляют собой кучу памяти, которая использует интерфейс клерков памяти чтобы получить доступ к page allocator для выделения страниц. Memory Objects не используют интерфейсы виртуальной или общей памяти, этот элемент использует только механизм распределения страниц. Многие компоненты SQL Server обращаются напрямую к MO, минуя клерки памяти. МО предоставляют возможность распределить диапазоны памяти произвольного размера.
Более подробно:
http://blogs.msdn.com/b/slavao/archive/2005/02/11/371063.aspx;
http://support.microsoft.com/kb/907877/en-us;
http://msdn.microsoft.com/ru-ru/library/ms179875.aspx.
Memory Broker (МВ)
Memory broker (брокер памяти) является компонентом SQLOS. Брокер памяти отвечает за распределение памяти между различными компонентами SQL Server в соответствии с их запросами. Более подробно можно прочитать на сайте производителя.
Рисунок 1.7 Распределение памяти Memory Broker
Описание механизма: МВ отслеживает запросы памяти от компонентов SQL и сопоставляет с текущими показатели её использования. Основываясь на полученной информации, брокер вычисляет «оптимальный» размер памяти, которая может быть распределена между компонентами. Брокер уведомляет компоненты о своих вычислениях, после этого каждый компонент использует эти сведения для дальнейшего использования памяти.
МВ можно увидеть в следующих динамических представлениях “sys.dm_os_ring_buffers”, где Ring_buffer_type = “RING_BUFFER_MEMORY_BROKER”. Подробнее можно прочитать здесь, здесь и здесь.
Resource semaphore
Resource Semaphore отвечают за выделение памяти компоненту и сохранение общего размера используемой памяти в пределах установленного лимита. Более подробно можно посмотреть на blogs.msdn.com и
mssqltips.com.
Автор: mikegrekov