In-Memory OLTP - Melhorias no Transaction Logging
In-Memory OLTP - Melhorias no Transaction Logging
O Transaction Log é responsável por gravar todas as modificações realizadas por uma transação. Ele é essencial para o caso de uma falha (ex. falta de energia) o arquivo de Log é fundamental no processo de Recovery e trazer o banco de dados a um estado consistente.
Podemos ainda dizer que a capacidade de gravação de um banco de dados é limitada pela capacidade de gravação dos dados no Transaction Log.
O SQL Server 2014 introduziu uma série de melhorias com relação ao transaction log, para que fosse possivel manter a consistencia dos dados das tabelas In-Memory. Isso se deve ao fato de que as tabelas na memória precisam persisitir no Log da mesma maneira que é feito hoje nas tabelas no disco.
A feature In-Memory do SQL Server 2014 foi criada principalmente para resolver problemas de concorrência física quando vários usuários ao mesmo mesmo tempo fazem alterações em uma mesma Página/Estrutura Física em memória, o que chamamos de concorrência por Latch.
As operações nas tabelas In-Memory são operações muito rápidas e para que a performance do In-Mermory não fosse prejudicada foram feitas uma série de melhorias com relação ao transacion Log, essas melhorias são as seguintes:
- As operações de Insert e delete requerem menos espaço de gravações do que as tabelas em disco.
- In-Mermoy OLTP tenta agupar os registros de Log em um grande registro de Log com até 24KB, e com isso reduzir a quantidade de escritas.
- Agora o In-Memory utiliza um modelo de concorrência otimista e as operações são gravadas apenas no momento do Commit, ao contrário das tabelas de disco que todos os passos erram gravados para possiblitar o Rollback das operações. Ou seja ele efetua todas alterações passo a passo e só grava no log no momento do Commit e isso reduz o número de vezes que uma transação precisa escrever no Log Buffer.
- As alterações nos índices In-Memory não são Logadas, com isso há um número muito menor de registros gerados no Transaction Log, caso ocorra restart da instância os índices das tabelas In-Memory são criados no processo de Recovery.
O ponto que gostaria de chamar atenção nesse artigo, é que além das melhorias citadas acima que ocorreram no produto, é recomendado que sejam utilizados discos SSD no volume onde é armazenado o arquivo de Log, caso contrário o ganho de performance com as tabelas In-Memory podem ser impossilitados ou suprimidos, porque mesmo as operações In-Memory (muito rápidas e sem Latch) precisam persistir no disco e quanto mais rapido a gravação no log ocorrer, melhor.
Veja agora uma DEMO que ilustra uma grande redução de Log nas transações das tabelas In-Memory:
O trecho abaixo irá criar um banco de dados com o nome de Demolog
USE master
GO
IF EXISTS (SELECT * FROM sys.databases WHERE name='DemoLog')
DROP DATABASE DemoLog;
GO
CREATE DATABASE DemoLog ON
PRIMARY (NAME= [DemoLog_data], FILENAME ='C:\DataHK\DemoLog_data.mdf'),
FILEGROUP [DemoLog_FG] CONTAINS MEMORY_OPTIMIZED_DATA
(NAME= [DemoLog_InMemory1], FILENAME = 'C:\DataHK\StorageDemo_DemoLog_InMemory1')
LOG ON (name = [DemoLog_log], Filename='C:\DataHK\StorageDemoLog_InMemory_log.ldf', size=100MB);
GO
--Agora vamos criar duas tabelas uma em Memoria com o nome de InMemoryLog e outra no disco com nome de DiscoLog.
USE DemoLog
GO
IF EXISTS (SELECT * FROM sys.objects WHERE name='InMemoryLog')
DROP TABLE [dbo].[InMemoryLog]
GO
-- Cria uma tabela In-Memory
CREATE TABLE [dbo].[InMemoryLog]
( [Campo1] int NOT NULL,
[Campo2] char(100) NOT NULL,
CONSTRAINT [pk_InMemoryLog_campo1] PRIMARY KEY NONCLUSTERED HASH ([campo1])
WITH(BUCKET_COUNT = 1000000)
) WITH (MEMORY_OPTIMIZED =ON,
DURABILITY = SCHEMA_AND_DATA);
GO
IF EXISTS (SELECT * FROM sys.objects WHERE name='DiscoLog')
DROP TABLE [dbo].[DiscoLog]
GO
--Vamos criar uma tabela similar no disco.
CREATE TABLE [dbo].[DiscoLog]
( [Campo1] int NOT NULL,
[Campo2] char(100) NOT NULL)
GO
CREATE UNIQUE NONCLUSTERED INDEX ix_discoLog_campo1 on DiscoLog(Campo1);
GO
--Agora vamos inserir alguns registros na tabela e examinar o log com a função fn_dblog().
BEGIN TRAN
DECLARE @i int = 0
WHILE (@i < 100)
BEGIN
INSERT INTO DiscoLog VALUES (@i, replicate ('1', 100))
SET @i = @I + 1
END
COMMIT
--Veja que foram inseridos 200 registros no log.
SELECT *
FROM sys.fn_dblog(NULL, NULL)
WHERE PartitionId IN
(SELECT partition_id FROM sys.partitions
WHERE object_id=object_id('DiscoLog'))
ORDER BY [Current LSN] ASC;
GO
--Agora vamos rodar um script similar para inserir os dados nas tabelas In-Memory
BEGIN TRAN
DECLARE @i int = 0
WHILE (@i < 100)
BEGIN
INSERT INTO InMemoryLog VALUES (@i, replicate ('1', 100))
SET @i = @i + 1
END
COMMIT
-- Olhe o Log
SELECT *
FROM sys.fn_dblog(NULL, NULL) order by [Current LSN] DESC;
GO
Veja na imagem acima que há apenas um registro de LOG para todos os 100 Inserts com o tipo de LOP_HK, LOP indica que é uma operação lógica e HK é a inicial do do nome Hekaton que era o nome do projeto do In-Memory.
Agora utilize a query abaixo para visualizar o registros agrupados In-Memory (Veja o LSN da operação).
SELECT [current lsn], [transaction id], operation,
operation_desc, tx_end_timestamp, total_size,
object_name(table_id) AS TableName
FROM sys.fn_dblog_xtp(null, null)
WHERE [Current LSN] = '00000020:0000015f:0004';
Com isso, termino minha explicação sobre Log no In-Memory, espero que tenham gostado, até a próxima!
Alberto Lima - SQL Server PFE
Comments
- Anonymous
July 21, 2015
Muito bom o artigo Alberto! Abraço!