Поделиться через


Введение в таблицы, оптимизированные для памяти

Применимо к:SQL ServerБаза данных SQL AzureУправляемый экземпляр SQL Azure

Таблицы, оптимизированные для памяти, создаются с помощью CREATE TABLE (Transact-SQL).

Таблицы, оптимизированные для памяти, по умолчанию полностью устойчивы. Как и транзакции на (стандартных) дисковых таблицах, транзакции на оптимизированных для памяти таблицах полностью соответствуют классификации ACID (atomic, consistent, isolated, durable — атомарные, целостные, изолированные и устойчивые). Оптимизированные для памяти таблицы и скомпилированные в собственном коде хранимые процедуры поддерживают только подмножество функций Transact-SQL.

Начиная с SQL Server 2016 и в Базе данных SQL Azure, нет ограничений для параметров сортировки или кодовых страниц , относящихся к In-Memory OLTP.

Первичное хранилище для таблиц, оптимизированных для памяти, — это основная память. Строки из таблицы считываются и записываются в память. Вторая копия табличных данных хранится на диске, но только с целью увеличения устойчивости. Дополнительные сведения о устойчивых таблицах см. в статье "Создание и управление хранилищем для объектов Memory-Optimized ". Данные в таблицах, оптимизированных для памяти, считываются только с диска во время восстановления базы данных (например, после перезапуска сервера).

Чтобы еще больше повысить производительность, OLTP в памяти поддерживает устойчивые таблицы с отложенной устойчивостью транзакций. Отложенные устойчивые транзакции сохраняются на диске вскоре после фиксации транзакции и управление возвращается клиенту. В обмен на повышение производительности зафиксированные, но несохранённые транзакции, которые не записаны на диск, теряются в случае сбоя сервера или переключения на резервный сервер.

Помимо таблиц, оптимизированных для долговременной памяти по умолчанию, SQL Server также поддерживает неустойчивые оптимизированные для памяти таблицы, которые не регистрируются, и их данные не сохраняются на диске. Это означает, что транзакции в этих таблицах не требуют операций ввода-вывода на диск, но данные теряются в случае сбоя сервера или переключения на резервный сервер.

OLTP в памяти интегрирован с SQL Server, чтобы обеспечить простой интерфейс во всех областях, таких как разработка, развертывание, управляемость и поддержка. База данных может содержать как объекты в памяти, так и объекты на диске.

Строки в оптимизированных для памяти таблицах имеют версии. То есть каждая строка в таблице потенциально имеет несколько версий. Все версии строк сохраняются в одной структуре данных таблицы. Управление версиями строк используется, чтобы разрешить параллельный режим чтения и записи для одной строки. Дополнительные сведения о параллельных операциях чтения и записи в одной строке см. в разделе "Транзакции с Memory-Optimized таблицами".

На следующем рисунке показана работа с несколькими версиями строк. На схеме показана таблица с тремя строками, у каждой строки своя версия.

Многоверсийность.

Таблица содержит три строки: r1, r2 и r3. r1 содержит три версии, r2 — 2 версии, и r3 — 4 версии. Разные версии одной строки не обязательно занимают последовательное расположение памяти. Различные версии строк могут быть распределены по всей структуре данных таблицы.

Структуру данных таблицы, оптимизированной для памяти, можно рассматривать как коллекцию версий строк. Строки в таблицах, сохраняемых на диске, разбиты по страницам и расширениям, при этом доступ к отдельным строкам осуществляется через номер страницы и смещение. Доступ к версиям строк в таблицах с оптимизацией для памяти осуществляется посредством указателей памяти, занимающих 8 байт.

Доступ к данным в таблицах, оптимизированных для памяти, можно получить двумя способами:

  • Использование хранимых процедур, скомпилированных в собственном коде.

  • С помощью интерпретированного Transact-SQL вне скомпилированной хранимой процедуры. Эти инструкции Transact-SQL могут находиться в интерпретированных хранимых процедурах или могут быть нерегламентированными инструкциями Transact-SQL.

Доступ к данным в оптимизированных для памяти таблицах

Доступ к оптимизированным для памяти таблицам можно получить наиболее эффективно из нативно скомпилированных хранимых процедур (нативно скомпилированные хранимые процедуры). Кроме того, к таблицам, оптимизированным для памяти, можно получить доступ с помощью (традиционного) интерпретированного Transact-SQL. Интерпретированный Transact-SQL относится к доступу к оптимизированным для памяти таблицам без скомпилированной хранимой процедуры в собственном коде. Некоторые примеры интерпретированного доступа Transact-SQL включают доступ к таблице, оптимизированной для памяти, из триггера DML, нерегламентированного пакета Transact-SQL, представления и табличного значения функции.

В следующей таблице приведены сведения о собственном и интерпретируемом доступе Transact-SQL для различных объектов.

Функция Доступ с помощью хранимой процедуры, скомпилированной в собственном коде Интерпретируемый доступ Transact-SQL Доступ по CLR-адресу
Таблица, оптимизированная для памяти Да Да Нет1
Табличный тип, оптимизированный для памяти Да Да Нет
Хранимая процедура, скомпилированная в собственном коде Вложение скомпилированных в собственном коде хранимых процедур поддерживается. Синтаксис EXECUTE можно использовать внутри хранимых процедур при условии, что соответствующие процедуры также скомпилированы в собственном коде. Да Нет*

1Невозможно получить доступ к оптимизированной для памяти таблице или скомпилированной в собственном коде хранимой процедуре из контекстного подключения (подключение из SQL Server при выполнении модуля CLR). Однако можно создать и открыть другое соединение, из которого можно получить доступ к оптимизированным для памяти таблицам и хранимым процедурам, скомпилированным в собственном коде.

Конфиденциальные данные в таблицах, оптимизированных для памяти, можно защитить с помощью Always Encrypted. Действительны следующие ограничения.

  • При использовании Always Encrypted с безопасными анклавами использование ключей с поддержкой анклава для столбцов в таблицах, оптимизированных для памяти, не поддерживается. Это означает, что не удается использовать шифрование на месте, и начальное шифрование выполняется на клиенте.
  • Always Encrypted не поддерживается ни для одного столбца в таблице, оптимизированной для памяти, если таблица ссылается в модуле с собственной компиляцией.

Производительность и масштабируемость   

Следующие факторы влияют на повышение производительности, которые можно достичь с помощью In-Memory OLTP:

Коммуникация: Приложение, использующее множество коротких вызовов хранимой процедуры, может увидеть меньший рост производительности по сравнению с приложением с меньшим количеством вызовов и дополнительными функциями, реализованными в каждой хранимой процедуре.

Transact-SQL Выполнение: In-Memory OLTP обеспечивает лучшую производительность при использовании нативно скомпилированных хранимых процедур, а не интерпретированных хранимых процедур или выполнения запросов напрямую. Иногда удобно получать доступ к оптимизированным для памяти таблицам из таких хранимых процедур.

Проверка диапазона и поиск точки: Оптимизированные для памяти некластеризованные индексы поддерживают проверки диапазона и упорядоченные проверки. С уточняющими запросами оптимизированные для памяти хэш-индексы более производительны, чем оптимизированные для памяти некластеризованные индексы. Оптимизированные для памяти некластеризованные индексы имеют более высокую производительность, чем дисковые индексы.

  • Начиная с версии SQL Server 2016 план запроса оптимизированной для памяти таблицы может сканировать таблицу в параллельном режиме. Это повышает производительность аналитических запросов.
    • Хэш-индексы также стали поддерживать сканирование в параллельном режиме в SQL Server 2016.
    • Некластеризованные индексы также стали поддерживать сканирование в параллельном режиме в SQL Server 2016.

Операции с индексами: Операции индекса не регистрируются, и они существуют только в памяти.

Параллелизм: Приложения, на которые влияет параллелизм на уровне движка, такие как соперничество за защелку или блокирование, значительно улучшают производительность при переходе на In-Memory OLTP.

В следующей таблице перечислены проблемы с производительностью и масштабируемостью, которые часто встречаются в реляционных базах данных, и описывается, как OLTP в памяти может улучшить производительность.

Проблема Влияние OLTP в памяти
Производительность

Высокая загрузка ресурсов (ЦП, операций ввода-вывода, сети или памяти).
ЦП
Скомпилированные хранимые процедуры в собственном коде могут значительно снизить использование ЦП, так как они требуют меньше инструкций для выполнения инструкции Transact-SQL по сравнению с интерпретируемыми хранимыми процедурами.

In-Memory OLTP может помочь сократить объем аппаратных инвестиций в масштабируемые рабочие нагрузки, так как один сервер может обеспечить пропускную способность нескольких серверов.

ВВОД-ВЫВОД
OLTP в памяти может уменьшить влияние узких мест в операциях ввода-вывода при обработке страниц данных или индекса. Кроме того, контроль точек In-Memory объектов OLTP является непрерывным и не приводит к внезапному увеличению операций ввода-вывода. Однако, если рабочий набор критически важных таблиц производительности не помещается в память, In-Memory OLTP не применяется, так как требуется, чтобы данные были в памяти. Если возникает задержка в операциях ввода-вывода при ведении журнала, то OLTP в памяти может снизить эту задержку, так как в журнал записывается меньше данных. Если одна или несколько таблиц, оптимизированных для памяти, настроены как устойчивые, журналирование данных можно исключить.

Память
In-Memory OLTP не предоставляет никаких преимуществ производительности. OLTP в памяти может вызывать дополнительную нагрузку на память, так как объекты должны быть резидентными.

Сеть
In-Memory OLTP не предоставляет никаких преимуществ производительности. Данные нужно передавать с уровня данных на уровень приложения.
Масштабируемость

Большинство проблем масштабирования в приложениях SQL Server вызваны проблемами параллелизма, такими как конфликт в блокировках, блокировках и спин-блокировках.
Конфликты кратковременных блокировок
Типичный сценарий — конфликт на последней странице индекса при параллельной вставке строк в порядке значений ключей. Так как In-Memory OLTP не использует блокировки при доступе к данным, проблемы с масштабируемостью, связанные с блокировками, полностью устраняются.

Конфликт спин-блокировок
Так как при доступе к данным не требуется In-Memory OLTP, проблемы масштабируемости, связанные с конфликтов спин-блокировки, полностью удаляются.

Конфликты, связанные с блокировкой
OLTP в памяти устраняет критические препятствия между операциями чтения и записи в приложении базы данных, поскольку используется новая форма управления оптимистической конкуренцией для реализации всех уровней изоляции транзакций. In-Memory OLTP не использует TempDB для хранения версий строк.

Если ошибка масштабирования вызвана конфликтом между двумя операциями записи, например двумя параллельными транзакциями, которые пытаются обновить одну и ту же строку, OLTP в памяти позволяет завершить одну транзакцию и отклоняет другую. Неудавшуюся транзакцию следует повторно отправить, либо явно, либо неявно, чтобы повторить транзакцию. В любом случае необходимо внести изменения в приложение.

Если в приложении часто возникают конфликты между двумя операциями записи, значимость оптимистической блокировки уменьшается. Приложение не подходит для In-Memory OLTP. Большинство приложений OLTP не сталкиваются с конфликтами при записи, за исключением случаев, когда конфликт является результатом эскалации блокировки.

Безопасность на уровне строк в оптимизированных для памяти таблицах

Row-Level Безопасность поддерживается в таблицах, оптимизированных для памяти. Применение политик безопасности на уровне строк в таблицах, оптимизированных для памяти, практически не отличается от применения политик в таблицах на дисках, за исключением того, что встроенные функции с табличным значением, используемые в качестве предикатов безопасности, должны быть скомпилированы в собственном коде (созданы с помощью параметра WITH NATIVE_COMPILATION). Дополнительные сведения см. в разделе "Совместимость между функциями " в разделе Row-Level "Безопасность ".

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

EXECUTE AS CALLER — все собственные модули теперь поддерживают и используют EXECUTE AS CALLER по умолчанию, даже если указание не указано. Это связано с тем, что все функции предиката безопасности на уровне строк используют EXECUTE AS CALLER, чтобы функция и все встроенные функции, которые она использует, вычислялись в контексте вызывающего пользователя.
Производительность предложения EXECUTE AS CALLER немного снижена (приблизительно на 10 %) из-за проверок разрешений вызывающего объекта. Если модуль указывает EXECUTE AS OWNER или EXECUTE AS SELF явным образом, эти проверки разрешений и связанные с ними затраты на производительность будут избегаться. Однако использование любого из этих вариантов вместе с упомянутыми встроенными функциями приводит к снижению производительности из-за необходимого переключения контекста.

Сценарии

Краткое обсуждение типичных сценариев, в которых In-Memory OLTP может повысить производительность, см. In-Memory OLTP.

См. также

In-Memory OLTP (оптимизацияIn-Memory)