Compartilhar via


Introdução às tabelas com otimização de memória

Aplica-se a:SQL ServerBanco de Dados SQL do AzureInstância Gerenciada de SQL do Azure

Tabelas com otimização de memória são criadas usando CREATE TABLE (Transact-SQL).

Por padrão, as tabelas com otimização de memória são completamente duráveis e, assim como as transações em tabelas com base em disco tradicionais, elas são completamente ACID (atômico, consistente, isolado e durável). As tabelas com otimização de memória e procedimentos armazenados compilados nativamente só são compatíveis com um subconjunto de recursos do Transact-SQL.

Começando com o SQL Server 2016 e no banco de dados SQL do Azure, não há nenhuma limitação para ordenações ou páginas de código que são específicos para OLTP na memória.

O repositório primário para tabelas com otimização de memória é a memória principal. As linhas da tabela são lidas e gravadas na memória. Uma segunda cópia dos dados da tabela é mantida em disco, mas apenas para fins de durabilidade. Consulte Criando e gerenciando o armazenamento para objetos Memory-Optimized para obter mais informações sobre tabelas duráveis. Os dados em tabelas com otimização de memória são lidos apenas do disco durante a recuperação do banco de dados (por exemplo, após a reinicialização do servidor).

Para obter ganhos de desempenho ainda maiores, o OLTP na Memória oferece suporte a tabelas duráveis com a durabilidade da transação atrasada. Transações duráveis atrasadas são salvas em disco logo após a transação ser confirmada e o controle é retornado ao cliente. Em troca do aumento do desempenho, as transações confirmadas que não são persistentes no disco são perdidas em uma falha ou failover do servidor.

Além das tabelas duráveis com otimização de memória padrão, o SQL Server também dá suporte a tabelas não duráveis com otimização de memória, que não são registradas e seus dados não são persistidos no disco. Isso significa que as transações nessas tabelas não exigem nenhuma E/S de disco, mas os dados serão perdidos se houver uma falha ou failover do servidor.

O OLTP in-memory é integrado ao SQL Server para fornecer uma experiência perfeita em todas as áreas, como desenvolvimento, implantação, capacidade de gerenciamento e capacidade de suporte. Um banco de dados pode conter objetos residentes na memória e baseados em disco.

As linhas nas tabelas com otimização de memória têm controle de versão. Isso significa que cada linha da tabela, possivelmente, tem várias versões. Todas as versões de linha são mantidas na mesma estrutura de dados da tabela. O controle de versão de linha é usado para permitir leituras e gravações simultâneas na mesma linha. Para obter mais informações sobre leituras e gravações simultâneas na mesma linha, consulte Transações com tabelas de Memory-Optimized.

A figura a seguir ilustra o controle de várias versões. A figura mostra uma tabela com três linhas, e cada linha tem versões diferentes.

Controle de várias versões.

A tabela tem três linhas: r1, r2 e r3. r1 tem três versões, r2 tem duas versões e r3 tem quatro versões. Versões diferentes da mesma linha não necessariamente ocupam locais de memória consecutivos. As versões de linha diferentes podem ser dispersas em toda a estrutura de dados da tabela.

A estrutura de dados da tabela com otimização de memória pode ser considerada uma coleção de versões de linha. As linhas nas tabelas baseadas em disco são organizadas em páginas e extensões, e as linhas individuais são resolvidas através do número e do deslocamento da página, as versões de linha nas tabelas com otimização de memória são resolvidas através dos ponteiros de memória de 8 bytes.

Os dados nas tabelas com otimização de memória são acessados de duas maneiras:

  • Por meio de procedimentos armazenados compilados nativamente.

  • Por meio do Transact-SQL interpretado, fora de um procedimento armazenado compilado nativamente. Essas instruções Transact-SQL podem ser procedimentos armazenados interpretados internos ou instruções Transact-SQL ad hoc.

Acessando dados nas tabelas com otimização de memória

As tabelas com otimização de memória podem ser acessadas com mais eficiência a partir de procedimentos armazenados compilados nativamente (procedimentos armazenados compilados nativamente). As tabelas com otimização de memória também podem ser acessadas com Transact-SQL interpretado (tradicional). O Transact-SQL interpretado se refere-ao acesso a tabelas com otimização de memória sem um procedimento armazenado compilado nativamente. Alguns exemplos de acesso ao Transact-SQL interpretado incluem o acesso a uma tabela com otimização de memória de um gatilho DML de um lote Transact-SQL ad hoc, de uma exibição e de uma função com valor de tabela.

A tabela a seguir resume o acesso ao Transact-SQL nativo e interpretado para vários objetos.

Recurso Acesso através de um procedimento armazenado compilado nativamente Acesso ao Transact-SQL interpretado Acesso à CLR
Tabela com otimização de memória Sim Sim Não1
Tipo de tabela com otimização de memória Sim Sim Não
Procedimento armazenado compilado nativamente Agora há suporte para o aninhamento de procedimentos armazenados nativamente compilados. Você pode usar a sintaxe EXECUTE dentro dos procedimentos armazenados, desde que o procedimento referenciado também seja nativamente compilado. Sim Não*

1Você não pode acessar uma tabela com otimização de memória ou um procedimento armazenado compilado nativamente da conexão de contexto (a conexão do SQL Server ao executar um módulo CLR). No entanto, é possível criar e abrir outra conexão, da qual você pode acessar tabelas com otimização de memória e procedimentos armazenados compilados nativamente.

Dados confidenciais em tabelas com otimização de memória podem ser protegidos usando o Always Encrypted. As seguintes limitações se aplicam:

  • Ao usar o Always Encrypted com enclaves seguros, não há suporte para o uso de chaves habilitadas para enclave para colunas em tabelas com otimização de memória. Isso significa que a criptografia no local não pode ser usada e a criptografia inicial é feita no cliente.
  • O Always Encrypted não tem suporte para nenhuma coluna em uma tabela com otimização de memória quando a tabela é referenciada em um módulo compilado nativamente.

Desempenho e escalabilidade

Os seguintes fatores afetam os ganhos de desempenho que podem ser obtidos com In-Memory OLTP:

Comunicação: Um aplicativo que usa muitas chamadas de procedimento armazenado curto pode ver um ganho de desempenho menor em comparação com um aplicativo com menos chamadas e mais funcionalidades implementadas em cada procedimento armazenado.

Transact-SQL Execução: In-Memory OLTP obtém o melhor desempenho ao usar procedimentos armazenados compilados nativamente em vez de procedimentos armazenados interpretados ou execução de consulta. Pode ser vantajoso acessar tabelas com otimização de memória de tais procedimentos armazenados.

Escaneamento de Intervalo vs Consulta de Ponto: Índices não clusterizados otimizados para memória dão suporte a escaneamentos de intervalo e escaneamentos ordenados. Para pesquisas de ponto, os índices de hash com otimização de memória têm desempenho melhor que os índices não clusterizados com otimização de memória. Os índices não clusterizados com otimização de memória têm desempenho melhor que os índices baseados em disco.

  • A partir do SQL Server 2016, o plano de consulta de uma tabela com otimização de memória pode examinar a tabela em paralelo. Isso melhora o desempenho de consultas analíticas.
    • Índices de hash também se tornaram verificáveis em paralelo no SQL Server 2016.
    • Índices não clusterizados também se tornaram verificáveis em paralelo no SQL Server 2016.

Operações de índice: As operações de índice não são registradas e existem apenas na memória.

Concorrência: Aplicativos cujo desempenho é afetado pela concorrência a nível de mecanismo, como contenção de travas ou bloqueios, melhoram significativamente quando o aplicativo é transferido para In-Memory OLTP.

A tabela a seguir lista os problemas de desempenho e escalabilidade que geralmente são encontrados em bancos de dados relacionais e como o OLTP na memória pode melhorar o desempenho.

Problema Impacto do OLTP na memória
Desempenho

Uso de alto recurso (CPU, E/S, rede ou memória).
CPU (Unidade Central de Processamento)
Procedimentos armazenados compilados nativamente podem reduzir significativamente o uso da CPU porque exigem menos instruções para executar uma instrução Transact-SQL em comparação com procedimentos armazenados interpretados.

In-Memory OLTP pode ajudar a reduzir o investimento em hardware em cargas de trabalho escaláveis porque um servidor pode potencialmente fornecer o desempenho de vários servidores.

E/S
Se você encontrar um gargalo de E/S, do processamento às páginas de dados ou índice, o OLTP na memória poderá reduzir esse gargalo. Além disso, o ponto de verificação de objetos OLTP na memória é contínuo e não leva a aumentos repentinos nas operações de E/S. No entanto, se o conjunto de trabalho das tabelas críticas de desempenho não cabe na memória, In-Memory OLTP não se aplica porque os dados precisam estar na memória. Se você encontrar um gargalo de E/S no log, o OLTP na memória poderá reduzi-lo, pois ele gera menos registros. Se uma ou mais tabelas com otimização de memória forem configuradas como tabelas não duráveis, você poderá eliminar o registro de dados.

Memória
In-Memory OLTP não oferece nenhum benefício de desempenho. Além disso, o OLTP na memória pode fazer mais pressão na memória, pois os objetos precisam ser residentes na memória.

Rede
In-Memory OLTP não oferece nenhum benefício de desempenho. Os dados precisam ser comunicados da camada de dados à camada de aplicativos.
Escalabilidade

A maioria dos problemas de escala nos aplicativos do SQL Server é causada por problemas de simultaneidade, como contenção em bloqueios, travas e spinlocks.
Contenção de trava
Um cenário típico é a contenção na última página de um índice na inserção de linhas simultaneamente na ordem de chave. Como In-Memory OLTP não usa travas ao acessar dados, os problemas de escalabilidade relacionados a contenções de trava são totalmente removidos.

Contenção de spinlock
Como In-Memory OLTP não usa travas ao acessar dados, os problemas de escalabilidade relacionados a contenções de spinlock são totalmente removidos.

Contenção relacionada ao bloqueio
Se seu aplicativo de banco de dados detectar problemas de bloqueio entre operações de leitura e gravação, o OLTP na memória removerá esses problemas, pois ele usa um novo formulário de controle de simultaneidade otimista para implementar todos os níveis de isolamento de transação. In-Memory OLTP não usa TempDB para armazenar versões de linha.

Se o problema de colocação em escala for causado por um conflito entre duas operações de gravação, como duas transações simultâneas tentando atualizar a mesma linha, o OLTP na memória permitirá que uma transação tenha êxito e que a outra falhe. A transação com falha deve ser reenviada explicitamente ou implicitamente, repetindo a transação. Em ambos os casos, você precisa fazer alterações no aplicativo.

Se seu aplicativo apresentar conflitos frequentes entre duas operações de gravação, o valor do bloqueio otimista será diminuído. O aplicativo não é adequado para In-Memory OLTP. A maioria dos aplicativos OLTP não tem conflitos de gravação, a menos que o conflito seja o resultado do escalonamento de bloqueios.

Segurança em nível de linha em tabelas com otimização de memória

Há suporte para asegurança em nível de linha em tabelas com otimização de memória. Aplicar políticas de segurança de nível de linha a tabelas com otimização de memória é essencialmente o mesmo que fazê-lo a tabelas baseadas em disco, exceto que as funções embutidas com valor de tabela usadas como predicados de segurança devem ser compiladas nativamente (criadas usando a opção WITH NATIVE_COMPILATION). Para obter detalhes, consulte a seção Compatibilidade entre recursos no tópico Row-Level Segurança .

Várias funções de segurança internas que são essenciais para a segurança em nível de linha estão disponíveis para tabelas com otimização de memória. Para obter detalhes, consulte funções internas em módulos compilados nativamente.

EXECUTE AS CALLER - Todos os módulos nativos agora dão suporte e usam EXECUTE AS CALLER por padrão, mesmo que a indicação não seja especificada. Isso ocorre porque é esperado que todas as funções de predicado de segurança em nível de linha usem EXECUTE AS CALLER para que a função e quaisquer funções internas usadas nela sejam avaliadas no contexto do usuário chamador.
EXECUTE AS CALLER tem um impacto pequeno (aproximadamente 10%) sobre o desempenho causado pelas verificações de permissão no chamador. Se o módulo especificar EXECUTE AS OWNER ou EXECUTE AS SELF explicitamente, essas verificações de permissão e o custo de desempenho associado serão evitados. No entanto, o uso de qualquer uma dessas opções junto com as funções internas mencionadas incorre em um maior impacto de desempenho devido à mudança de contexto necessária.

Cenários

Para obter uma breve discussão sobre cenários típicos em que In-Memory OLTP pode melhorar o desempenho, consulte In-Memory OLTP.

Confira também

OLTP na memória (otimização na memória)