Exemplo de in-memory no Banco de Dados SQL do Azure
Aplica-se a: Banco de Dados SQL do Azure
As tecnologias In-Memory no Banco de Dados SQL do Azure que podem melhorar o desempenho do seu aplicativo e reduzir potencialmente o custo do banco de dados. Ao usar tecnologias In-Memory no Banco de Dados SQL do Azure, obtenha melhorias de desempenho com várias cargas de trabalho.
Neste artigo, duas amostras ilustram o uso do OLTP in-memory, bem como os índices columnstore no Banco de Dados SQL do Azure.
Para saber mais, veja:
- Visão geral e cenários de uso do OLTP In-Memory (incluindo referências a estudos de caso de cliente e informações para começar)
- Documentação para OLTP in-memory
- Guia de Índices columnstore
- HTAP (Processamento Transacional e Analítico Híbrido), também conhecido como análise operacional em tempo real
Para obter uma demonstração introdutória do OLTP in-memory, consulte:
- Versão: in-memory-oltp-demo-v1.0
- Código-fonte: in-memory-oltp-demo-source-code
1. Instalar o exemplo de OLTP Na Memória.
Você pode criar o banco de dados de exemplo AdventureWorksLT
em algumas etapas no Portal do Azure. Em seguida, use as etapas nesta seção para adicionar objetos OLTP in-memory ao seu banco de dados AdventureWorksLT
e demonstrar os benefícios de desempenho.
Etapas de instalação
No portal do Azure, crie um banco de dados Premium (DTU) ou Comercialmente Crítico (vCore) em um servidor lógico. Defina a Origem como o banco de dados de exemplo
AdventureWorksLT
. Para obter instruções detalhadas, confira Criar seu primeiro banco de dados no Banco de Dados SQL do Azure.Conecte-se ao banco de dados com o SQL Server Management Studio (SSMS)
Copie o script Transact-SQL do OLTP Na Memória para a área de transferência. O script T-SQL cria os objetos necessários in-memory no banco de dados de exemplo
AdventureWorksLT
criado na etapa 1.Cole o script T-SQL no SSMS e execute o script. A cláusula
MEMORY_OPTIMIZED = ON
nas declaraçõesCREATE TABLE
é crucial. Por exemplo:CREATE TABLE [SalesLT].[SalesOrderHeader_inmem]( [SalesOrderID] int IDENTITY NOT NULL PRIMARY KEY NONCLUSTERED ..., ... ) WITH (MEMORY_OPTIMIZED = ON);
Erro 40536
Se você receber o erro 40536 quando executar o script T-SQL, execute o seguinte script T-SQL para verificar se o banco de dados oferece suporte a objetos in-memory:
SELECT DATABASEPROPERTYEX(DB_NAME(), 'IsXTPSupported');
Um resultado 0
significa que não há suporte para OLTP in-memory e 1
significa que há suporte. O OLTP in-memory está disponível nas camadas Banco de Dados SQL Premium (DTU) do Azure e Comercialmente Crítico (vCore).
Sobre os itens criados com otimização de memória
Tabelas: o exemplo contém as seguintes tabelas com otimização de memória:
SalesLT.Product_inmem
SalesLT.SalesOrderHeader_inmem
SalesLT.SalesOrderDetail_inmem
Demo.DemoSalesOrderHeaderSeed
Demo.DemoSalesOrderDetailSeed
Você pode filtrar para exibir apenas as tabelas com otimização de memória no Pesquisador de Objetos no SSMS. Ao clicar com o botão direito do mouse em Tabelas, navegue até >Filtro>Configurações de filtro>Com otimização de memória. O valor é igual a 1
.
Ou você pode consultar as exibições do catálogo, como:
SELECT is_memory_optimized, name, type_desc, durability_desc
FROM sys.tables
WHERE is_memory_optimized = 1;
Procedimento armazenado compilado nativamente: você pode inspecionar SalesLT.usp_InsertSalesOrder_inmem
por meio de uma consulta de exibição de catálogo:
SELECT uses_native_compilation, OBJECT_NAME(object_id) AS module_name, definition
FROM sys.sql_modules
WHERE uses_native_compilation = 1;
2. Executar a carga de trabalho OLTP
A única diferença entre os dois procedimentos armazenados a seguir é que o primeiro procedimento usa tabelas com otimização de memória, enquanto o segundo procedimento usa as tabelas em disco regulares:
SalesLT.usp_InsertSalesOrder_inmem
SalesLT.usp_InsertSalesOrder_ondisk
Nesta seção, você verá como usar o utilitário ostress.exe
para executar os dois procedimentos armazenados. Você pode comparar quanto tempo as duas execuções demoram para serem concluídas.
Instalar utilitários RML e o ostress
É recomendável executar ostress.exe
em uma VM (máquina virtual) do Azure. Você criaria uma VM do Azure na mesma região do Azure em que seu banco de dados AdventureWorksLT
está. Se for possível se conectar ao seu banco de dados SQL do Azure, também será possível executar ostress.exe
em sua máquina local. Contudo, a latência da rede entre sua máquina e o banco de dados no Azure pode reduzir os benefícios de desempenho do OLTP in-memory.
Na VM ou em qualquer host que você escolher, instale os utilitários RML (Replay Markup Language). Os utilitários incluem o ostress.exe
.
Para saber mais, veja:
- A discussão sobre o
ostress.exe
no Banco de dados de exemplo para OLTP In-Memory. - Banco de dados de exemplo para OLTP In-Memory.
Script para ostress.exe
Esta seção exibe o script T-SQL, que está inserido em nossa linha de comando do ostress.exe
. O script usa itens que foram criados pelo script T-SQL instalado anteriormente.
Quando executar o ostress.exe
, recomendamos será passar valores de parâmetro projetados para enfatizar a carga de trabalho usando ambas as seguintes estratégias:
- Execute um grande número de conexões simultâneas usando
-n100
. - Faça com que cada conexão se repita centenas de vezes usando
-r500
.
No entanto, talvez você queira começar com valores muito menores, como -n10
e -r50
para garantir que tudo esteja funcionando.
O script a seguir insere um pedido de vendas de exemplo com cinco itens de linha nas seguintes tabelascom otimização de memória:
SalesLT.SalesOrderHeader_inmem
SalesLT.SalesOrderDetail_inmem
DECLARE
@i int = 0,
@od SalesLT.SalesOrderDetailType_inmem,
@SalesOrderID int,
@DueDate datetime2 = sysdatetime(),
@CustomerID int = rand() * 8000,
@BillToAddressID int = rand() * 10000,
@ShipToAddressID int = rand() * 10000;
INSERT INTO @od
SELECT OrderQty, ProductID
FROM Demo.DemoSalesOrderDetailSeed
WHERE OrderID= cast((rand()*60) as int);
WHILE (@i < 20)
BEGIN;
EXECUTE SalesLT.usp_InsertSalesOrder_inmem @SalesOrderID OUTPUT,
@DueDate, @CustomerID, @BillToAddressID, @ShipToAddressID, @od;
SET @i = @i + 1;
END
Para criar a versão _ondisk do script T-SQL anterior para ostress.exe
, substitua as duas ocorrências da substring _inmem por _ondisk. Essas substituições afetam os nomes de tabelas e os procedimentos armazenados.
Executar a carga de trabalho de estresse do _inmem primeiro
Você pode usar uma janela RML Cmd Prompt para executar o ostress.exe
. Os parâmetros de linha de comando direcionam o ostress para:
- Execute 100 conexões simultaneamente (-n100).
- Faça cada conexão executar o script T-SQL 50 vezes (-r50).
ostress.exe -n100 -r50 -S<servername>.database.windows.net -U<login> -P<password> -d<database> -q -Q"DECLARE @i int = 0, @od SalesLT.SalesOrderDetailType_inmem, @SalesOrderID int, @DueDate datetime2 = sysdatetime(), @CustomerID int = rand() * 8000, @BillToAddressID int = rand() * 10000, @ShipToAddressID int = rand()* 10000; INSERT INTO @od SELECT OrderQty, ProductID FROM Demo.DemoSalesOrderDetailSeed WHERE OrderID= cast((rand()*60) as int); WHILE (@i < 20) begin; EXECUTE SalesLT.usp_InsertSalesOrder_inmem @SalesOrderID OUTPUT, @DueDate, @CustomerID, @BillToAddressID, @ShipToAddressID, @od; set @i += 1; end"
Para executar a linha de comando do ostress.exe
anterior:
Redefina o conteúdo de dados do banco de dados executando o seguinte comando no SSMS para excluir todos os dados inseridos por todas as execuções anteriores:
EXECUTE Demo.usp_DemoReset;
Copie o texto da linha de comando anterior do
ostress.exe
para a área de transferência.Substitua o
<placeholders>
para os parâmetros-S -U -P -d
pelos valores corretos.Execute a linha de comando editada em uma janela Cmd RML.
O resultado é uma duração
Quando o ostress.exe
é concluído, ele grava a duração da execução como sua linha final de saída na janela Cmd RML. Por exemplo, uma execução de teste mais curta dura aproximadamente 1,5 minuto:
11/12/15 00:35:00.873 [0x000030A8] OSTRESS exiting normally, elapsed time: 00:01:31.867
Redefinir, editar _ondisk e executar novamente
Depois de obter o resultado da execução do _inmem, realize as seguintes etapas para a execução de _ondisk:
Redefina o banco de dados executando o seguinte comando no SSMS para excluir todos os dados inseridos pela execução anterior:
EXECUTE Demo.usp_DemoReset;
Edite a linha de comando do
ostress.exe
para substituir todos os _inmem por _ondisk.Execute novamente o
ostress.exe
pela segunda vez e capture o resultado da duração.Redefina o banco de dados mais uma vez.
Resultados esperados para a comparação
Os testes do OLTP in-memory mostraram uma melhoria de desempenho de nove vezes para essa carga de trabalho simplista, com o ostress.exe
sendo executado em uma VM do Azure na mesma região do Azure que o banco de dados.
3. Instalar o exemplo de análise in-memory
Nesta seção, você vai comparar os resultados de E/S e de estatísticas ao usar um índice columnstore versus um índice b-tree tradicional.
Para fazer uma análise em tempo real em uma carga de trabalho OLTP, quase sempre será melhor usar um índice columnstore não clusterizado. Para ver mais detalhes, confira Índices Columnstore Descritos.
Preparar o teste de análise de columnstore
Use o portal do Azure para criar um novo banco de dados
AdventureWorksLT
desde o exemplo. Use qualquer objetivo de serviço que dê suporte a índices columnstore.Copie o sql_in-memory_analytics_sample para sua área de transferência.
- O script T-SQL cria os objetos necessários no banco de dados de exemplo
AdventureWorksLT
criado na etapa 1. - O script cria tabelas de dimensões e duas tabelas de fatos. As tabelas de fatos são preenchidas com 3,5 milhões de linhas cada.
- Em objetivos de serviço menores, o script pode levar 15 minutos ou mais para ser concluído.
- O script T-SQL cria os objetos necessários no banco de dados de exemplo
Cole o script T-SQL no SSMS e execute o script. A palavra-chave COLUMNSTORE na instrução
CREATE INDEX
é crucial:CREATE NONCLUSTERED COLUMNSTORE INDEX ...;
Configure
AdventureWorksLT
no nível de compatibilidade mais recente, o SQL Server 2022 (160):ALTER DATABASE AdventureworksLT SET compatibility_level = 160;
Tabelas chave e índices de columnstore
dbo.FactResellerSalesXL_CCI
é uma tabela com um índice columnstore clusterizado, que tem compactação avançada no nível de dados.dbo.FactResellerSalesXL_PageCompressed
é uma tabela com um índice clusterizado regular equivalente, compactado somente no nível de página.
4. Consultas chave para comparar o índice columnstore
Há diversos tipos de consulta T-SQL que podem ser executados para ver as melhorias de desempenho. Na etapa 2 no script T-SQL, preste atenção neste par de consultas. Elas diferem apenas em uma linha:
FROM FactResellerSalesXL_PageCompressed AS a
FROM FactResellerSalesXL_CCI AS a
Um índice columnstore clusterizado está na tabela FactResellerSalesXL_CCI
.
O script T-SQL a seguir imprime a atividade lógica de E/S e as estatísticas de tempo usando SET STATISTICS IO e SET STATISTICS TIME para cada consulta.
/*********************************************************************
Step 2 -- Overview
-- Page compressed BTree table vs Columnstore table performance differences
-- Enable actual query plan in order to see Plan differences when executing.
*/
-- Ensure the database uses the latest compatibility level
ALTER DATABASE AdventureworksLT SET compatibility_level = 160
GO
-- Execute a typical query that joins the fact table with dimension tables.
-- Note this query will run on the page compressed table. Note down the time.
SET STATISTICS IO ON
SET STATISTICS TIME ON
GO
SELECT c.Year
,e.ProductCategoryKey
,FirstName + ' ' + LastName AS FullName
,COUNT(SalesOrderNumber) AS NumSales
,SUM(SalesAmount) AS TotalSalesAmt
,AVG(SalesAmount) AS AvgSalesAmt
,COUNT(DISTINCT SalesOrderNumber) AS NumOrders
,COUNT(DISTINCT a.CustomerKey) AS CountCustomers
FROM FactResellerSalesXL_PageCompressed AS a
INNER JOIN DimProduct AS b ON b.ProductKey = a.ProductKey
INNER JOIN DimCustomer AS d ON d.CustomerKey = a.CustomerKey
INNER JOIN DimProductSubCategory AS e on e.ProductSubcategoryKey = b.ProductSubcategoryKey
INNER JOIN DimDate AS c ON c.DateKey = a.OrderDateKey
GROUP BY e.ProductCategoryKey,c.Year,d.CustomerKey,d.FirstName,d.LastName
GO
SET STATISTICS IO OFF
SET STATISTICS TIME OFF
GO
-- This is the same query on a table with a clustered columnstore index (CCI).
-- The comparison numbers are the more pronounced the larger the table is (this is an 11 million row table).
SET STATISTICS IO ON
SET STATISTICS TIME ON
GO
SELECT c.Year
,e.ProductCategoryKey
,FirstName + ' ' + LastName AS FullName
,COUNT(SalesOrderNumber) AS NumSales
,SUM(SalesAmount) AS TotalSalesAmt
,AVG(SalesAmount) AS AvgSalesAmt
,COUNT(DISTINCT SalesOrderNumber) AS NumOrders
,COUNT(DISTINCT a.CustomerKey) AS CountCustomers
FROM FactResellerSalesXL_CCI AS a
INNER JOIN DimProduct AS b ON b.ProductKey = a.ProductKey
INNER JOIN DimCustomer AS d ON d.CustomerKey = a.CustomerKey
INNER JOIN DimProductSubCategory AS e on e.ProductSubcategoryKey = b.ProductSubcategoryKey
INNER JOIN DimDate AS c ON c.DateKey = a.OrderDateKey
GROUP BY e.ProductCategoryKey,c.Year,d.CustomerKey,d.FirstName,d.LastName
GO
SET STATISTICS IO OFF
SET STATISTICS TIME OFF
GO
Em um banco de dados com o objetivo de serviço P2, você pode esperar um ganho de desempenho de cerca de nove vezes para essa consulta usando o índice columnstore clusterizado em comparação com o índice tradicional. Com o objetivo de serviço P15, você pode esperar cerca de 57 vezes o ganho de desempenho ao usar o índice columnstore.
Conteúdo relacionado
- Início Rápido 1: Tecnologias OLTP In-Memory para um desempenho mais rápido do T-SQL
- Usar o OLTP in-memory para melhorar o desempenho do aplicativo
- Monitorar o armazenamento OLTP in-memory
- Blog: OLTP in-memory no Banco de Dados SQL do Azure
- OLTP na memória
- Índices columnstore
- Análise operacional em tempo real índices columnstore
- Artigo técnico: OLTP in-memory – Padrões comuns de carga de trabalho e considerações de migração no SQL Server 2014