Database
 sql >> Base de Dados >  >> RDS >> Database

Mitos de desempenho:as variáveis ​​da tabela estão sempre na memória



Autor convidado:Derik Hammer (@SQLHammer)



Recentemente, Aaron Bertrand blogou sobre mitos prejudiciais e pervasivos sobre o desempenho do SQL Server. Como extensão desta série de blogs, vou refutar esse mito comum:
"As variáveis ​​de tabela estão sempre na memória, portanto, mais rápidas que as tabelas temporárias."

Ler o manual


Indo direto para a fonte, consultei o artigo Books Online sobre tabelas que inclui variáveis ​​de tabela. Embora o artigo faça referência aos benefícios do uso de variáveis ​​de tabela, o fato de elas estarem 100% na memória está claramente ausente.

Uma afirmativa ausente não implica uma negativa, no entanto. Desde que as tabelas OLTP na memória foram lançadas, agora há muito mais documentação em BOL para processamento na memória. Foi aí que encontrei este artigo sobre como tornar as variáveis ​​de tabela e tabela temporárias mais rápidas usando a otimização de memória.

O artigo inteiro gira em torno de como fazer com que seus objetos temporários usem o recurso OLTP na memória, e foi aí que encontrei a afirmativa que estava procurando.
"Uma variável de tabela tradicional representa uma tabela no banco de dados tempdb. Para um desempenho muito mais rápido, você pode otimizar a memória de sua variável de tabela."
As variáveis ​​de tabela não são construções na memória. Para usar a tecnologia in-memory, você precisa definir explicitamente um TYPE que seja otimizado para memória e usar esse TYPE para definir sua variável de tabela.

Prove


Documentação é uma coisa, mas ver com meus próprios olhos é outra bem diferente. Eu sei que as tabelas temporárias criam objetos no tempdb e gravam dados no disco. Primeiro, mostrarei como são as tabelas temporárias e, em seguida, usarei o mesmo método para validar a hipótese de que as variáveis ​​da tabela agem da mesma maneira.

Análise de registro de log


Essa consulta executará um CHECKPOINT para me fornecer um ponto de partida limpo e, em seguida, mostrará o número de registros de log e os nomes de transação que existem no log.
USE tempdb;
GO
 
CHECKPOINT;
GO
 
SELECT COUNT(*) [Count] 
  FROM sys.fn_dblog (NULL, NULL);
 
SELECT [Transaction Name]
  FROM sys.fn_dblog (NULL, NULL)
  WHERE [Transaction Name] IS NOT NULL;


Executar o T-SQL repetidamente resultou em uma contagem consistente de três registros no SQL Server 2016 SP1.

Isso cria uma tabela temporária e exibe o registro do objeto, provando que este é um objeto real no tempdb.
USE tempdb;
GO
 
DROP TABLE IF EXISTS #tmp;
GO
 
CREATE TABLE #tmp (id int NULL);
 
SELECT name
  FROM sys.objects o
  WHERE is_ms_shipped = 0;



Agora vou mostrar os registros de log novamente. Não vou executar novamente o comando CHECKPOINT.



Vinte e um registros de log foram gravados, provando que são gravações em disco, e nosso CREATE TABLE está claramente incluído nesses registros de log.

Para comparar esses resultados com as variáveis ​​de tabela, redefinirei o experimento executando CHECKPOINT e, em seguida, executando o T-SQL abaixo, criando uma variável de tabela.
USE tempdb;
GO
 
DECLARE @var TABLE (id int NULL);
 
SELECT name
  FROM sys.objects o
  WHERE is_ms_shipped = 0;



Mais uma vez temos um novo registro de objeto. Desta vez, no entanto, o nome é mais aleatório do que com tabelas temporárias.



Há oitenta e dois novos registros de log e nomes de transação provando que minha variável está sendo gravada no log e, portanto, no disco.

Na verdade, na memória


Agora é hora de eu fazer os registros de log desaparecerem.

Criei um grupo de arquivos OLTP na memória e, em seguida, criei um tipo de tabela com otimização de memória.
USE Test;
GO
 
CREATE TYPE dbo.inMemoryTableType  
  AS TABLE 
  ( id INT NULL INDEX ix1 )
  WITH (MEMORY_OPTIMIZED = ON);  
GO

Executei o CHECKPOINT novamente e criei a tabela otimizada de memória.
USE Test;
GO
 
DECLARE @var dbo.inMemoryTableType;
 
INSERT INTO @var (id) VALUES (1)
 
SELECT * from @var;  
GO

Depois de revisar o log, não vi nenhuma atividade de log. Este método é de fato 100% na memória.


Retirada


As variáveis ​​de tabela usam tempdb de forma semelhante a como as tabelas temporárias usam tempdb. As variáveis ​​de tabela não são construções na memória, mas podem se tornar elas se você usar tipos de tabela definidos pelo usuário com otimização de memória. Muitas vezes, acho que as tabelas temporárias são uma escolha muito melhor do que as variáveis ​​de tabela. A principal razão para isso é porque as variáveis ​​de tabela não têm estatísticas e, dependendo da versão e das configurações do SQL Server, as estimativas de linha são de 1 ou 100 linhas. Em ambos os casos, essas são suposições e se tornam peças prejudiciais de desinformação em seu processo de otimização de consulta.



Observe que algumas dessas diferenças de recursos podem mudar com o tempo – por exemplo, em versões recentes do SQL Server, você pode criar índices adicionais em uma variável de tabela usando a sintaxe de índice embutido. A tabela a seguir tem três índices; a chave primária (agrupada por padrão) e dois índices não agrupados:
DECLARE @t TABLE
(
  a int PRIMARY KEY,
  b int,
  INDEX x (b, a DESC),
  INDEX y (b DESC, a)
);

Há uma ótima resposta no DBA Stack Exchange, onde Martin Smith detalha exaustivamente as diferenças entre variáveis ​​de tabela e tabelas #temp:
  • Qual ​​é a diferença entre uma tabela temporária e uma variável de tabela no SQL Server?

Sobre o autor

Derik é um profissional de dados e MVP recém-criado da Microsoft Data Platform com foco no SQL Server. Sua paixão se concentra em alta disponibilidade, recuperação de desastres, integração contínua e manutenção automatizada. Sua experiência abrange administração de banco de dados de longo prazo, consultoria e empreendimentos empresariais trabalhando nos setores financeiro e de saúde. Ele é atualmente um Administrador Sênior de Banco de Dados responsável pela equipe de Operações de Banco de Dados na Sede Mundial da Subway Franchise. Quando não está no horário ou blogando no SQLHammer.com, Derik dedica seu tempo à #sqlfamily como líder de capítulo do grupo de usuários FairfieldPASS SQL Server em Stamford, CT.