

# Como usar o cache de análise do ANTLR no Babelfish
<a name="babelfish-procedure-parse-cache"></a>

A partir das versões 5.7.0 e 6.2.0 do Babelfish, é possível usar um cache persistente dos resultados da análise do ANTLR para rotinas armazenadas em T-SQL (procedimentos e funções) a fim de reduzir a latência da primeira execução.

**Com o cache de análise de procedimentos:**
+ Rotinas T-SQL grandes (com centenas a milhares de linhas) deixam de incorrer na sobrecarga da análise completa de T-SQL na primeira execução de cada nova sessão.
+ O resultado analisado é serializado uma única vez no momento de `CREATE`/`ALTER` do procedimento ou da função, armazenado no catálogo e reutilizado entre sessões, emulando o comportamento de cache global do sistema do SQL Server.
+ O recurso é controlado pelo GUC `babelfishpg_tsql.enable_antlr_parse_cache` no nível da sessão, com substituições opcionais por rotina por meio de `sys.enable_antlr_parse_cache()`.
+ Por padrão, o recurso fica **DESATIVADO**.

**Desempenho:** para rotinas grandes, a análise do ANTLR pode levar vários segundos. Com o cache de análise do ANTLR, o tempo de análise na primeira execução é reduzido a alguns milissegundos. As execuções subsequentes na mesma sessão são atendidas pelo cache da sessão (menos de um milissegundo) e não são afetadas.

## Noções básicas sobre o cache de análise do ANTLR
<a name="babelfish-procedure-parse-cache-overview"></a>

O Babelfish precisa validar a sintaxe T-SQL analisando o corpo de uma rotina na primeira vez que ela é executada em uma sessão. Normalmente, esse resultado da análise fica em cache apenas durante a sessão, portanto, cada nova conexão realiza a análise novamente desde o início. O cache de análise persiste o resultado no catálogo para que novas sessões possam reutilizá-lo.

Como funciona:
+ **Em `CREATE`/`ALTER`:** quando o cache está ativado, o Babelfish analisa a rotina e armazena o resultado serializado da análise no cache persistente.
+ **Primeira execução sem uma entrada persistente:** se não houver uma entrada em cache (por exemplo, se a rotina tiver sido criada antes da ativação do cache), o Babelfish executará a análise normal do ANTLR e preencherá o cache persistente.
+ **Primeira execução em uma sessão posterior:** o Babelfish carrega e desserializa o resultado da análise armazenado em cache em vez de analisá-lo novamente. É nesse ponto que ocorre a economia de tempo.
+ **Execuções subsequentes na mesma sessão:** são atendidas pelo cache da sessão (comportamento inalterado).
+ Se um resultado em cache estiver ausente ou tiver sido criado por uma versão diferente do Babelfish, o Babelfish executará a análise normal do ANTLR e preencherá novamente o cache persistente quando o cache estiver ativado.
+ Se o Babelfish encontrar um erro ao serializar ou desserializar um resultado em cache, a instrução falhará e retornará um erro. Desative o cache para a rotina afetada e tente executar a instrução novamente, ou tente executá-la em uma nova sessão com o GUC de cache desativado. Se o erro persistir, entre em contato com o suporte da AWS.

## Observação da melhoria no tempo de análise
<a name="babelfish-procedure-parse-cache-observing"></a>

É possível medir o efeito usando `SET BABELFISH_STATISTICS PROFILE ON`, que informa o `Babelfish T-SQL Batch Parsing Time` de cada lote. Primeiro, crie um procedimento grande com o cache ativado para preencher o cache persistente. Em seguida, compare a primeira execução do procedimento em duas sessões novas separadas: uma com o cache desativado, que ignora a entrada persistente, e outra com o cache ativado, que reutiliza essa entrada. Como alternativa, se o cache não estava ativado quando o procedimento foi criado, execute-o em duas sessões novas separadas, ambas com o cache ativado: a primeira execução preenche o cache persistente, e a segunda o reutiliza.

No exemplo a seguir, primeiro crie o procedimento com o cache ATIVADO para preencher o cache persistente:

```
-- New session 0: caching ON (at CREATE PROCEDURE time)
SELECT set_config('babelfishpg_tsql.enable_antlr_parse_cache', 'on', false);
GO
CREATE PROCEDURE dbo.updateInformation @region VARCHAR(50)
AS
BEGIN
    ...
END;
GO
```

Em seguida, em uma nova sessão com o cache DESATIVADO (o padrão), execute o procedimento:

```
-- New session 1: caching OFF (default)
SET BABELFISH_STATISTICS PROFILE ON;
GO
EXEC dbo.updateInformation @region = 'EMEA';   -- first call in this session
GO
```

O perfil de estatísticas informa um tempo de análise elevado:

```
Babelfish T-SQL Batch Parsing Time: 20359.465 ms
```

Por fim, em outra nova sessão com o cache ATIVADO, execute o procedimento:

```
-- New session 2: caching ON
SELECT set_config('babelfishpg_tsql.enable_antlr_parse_cache', 'on', false);
GO
SET BABELFISH_STATISTICS PROFILE ON;
GO
EXEC dbo.updateInformation @region = 'EMEA';   -- first call in this session
GO
```

O perfil de estatísticas informa um tempo de análise significativamente menor:

```
Babelfish T-SQL Batch Parsing Time: 150.927 ms
```

A primeira execução em uma nova sessão reduz o tempo de análise de aproximadamente 20 s para 0,15 s quando a árvore de análise armazenada em cache é reutilizada. A segunda execução e as posteriores na mesma sessão são atendidas pelo cache da sessão em ambos os casos (menos de um milissegundo) e não são afetadas pelo GUC.

## Ativação do cache para uma sessão
<a name="babelfish-procedure-parse-cache-enabling"></a>

O recurso é controlado por um GUC no nível da sessão (**DESATIVADO** por padrão):

```
-- Enable parse caching for the current session
SELECT set_config('babelfishpg_tsql.enable_antlr_parse_cache', 'on', false);
GO

-- Disable for the current session
SELECT set_config('babelfishpg_tsql.enable_antlr_parse_cache', 'off', false);
GO
```

**nota**  
O GUC **se aplica à sessão** e é redefinido para o valor padrão (DESATIVADO) quando a sessão termina.
Atualmente, **não** é possível configurar esse GUC em todo o cluster por meio de `sp_babelfish_configure`.

## Controle do cache por rotina
<a name="babelfish-procedure-parse-cache-per-routine"></a>

É possível substituir o GUC da sessão para uma rotina individual usando `sys.enable_antlr_parse_cache`, que aceita o ID do objeto da rotina:

```
-- Force caching ON for a specific routine (even if the session GUC is OFF)
SELECT sys.enable_antlr_parse_cache(sys.object_id('dbo.my_proc'), true);
GO

-- Force caching OFF for a specific routine — "kill switch"
-- (clears any cached data and blocks caching even if the session GUC is ON)
SELECT sys.enable_antlr_parse_cache(sys.object_id('dbo.my_proc'), false);
GO

-- Reset to default; the routine follows the session GUC
SELECT sys.enable_antlr_parse_cache(sys.object_id('dbo.my_proc'), NULL);
GO
```

**nota**  
É necessário ser o **proprietário** da rotina ou membro do perfil **sysadmin** para alterar a configuração de cache da rotina.
A configuração por rotina persiste entre sessões (ela é armazenada no catálogo) e é preservada entre `ALTER`; ela é removida quando a rotina é excluída.

## Verificação das estatísticas do cache
<a name="babelfish-procedure-parse-cache-stats"></a>

`sys.antlr_parse_cache_stats()` retorna a atividade do cache de análise para a sessão atual:

```
SELECT * FROM sys.antlr_parse_cache_stats();
GO
```

A tabela a seguir descreve cada coluna da saída.


| Coluna | Descrição | 
| --- | --- | 
| cache\_hits | Quantidade de execuções de rotinas nas quais um resultado de análise armazenado em cache foi reutilizado. | 
| cache\_misses | Quantidade de execuções de rotinas nas quais o cache estava ativado, mas não foi encontrada nenhuma entrada de cache utilizável. | 
| cache\_writes | Quantidade de gravações bem-sucedidas no cache persistente. | 
| cache\_evictions | Quantidade de entradas em cache que foram invalidadas ou removidas (por exemplo, devido ao mecanismo de desativação de emergência ou à alternância do GUC). | 
| cache\_errors | Quantidade de falhas de serialização ou desserialização. | 

Os contadores são específicos de cada sessão e são redefinidos ao estabelecer uma nova conexão.

## Exemplo de cenário
<a name="babelfish-procedure-parse-cache-example"></a>

```
-- Enable caching for this session
SELECT set_config('babelfishpg_tsql.enable_antlr_parse_cache', 'on', false);
GO

CREATE PROCEDURE dbo.report_proc @region VARCHAR(50)
AS
BEGIN
    -- large multi-statement T-SQL body ...
    SELECT @region;
END;
GO

-- First execution in a brand-new session: served from the persistent cache (fast)
EXEC dbo.report_proc @region = 'APAC';
GO

-- Inspect cache activity for this session
SELECT * FROM sys.antlr_parse_cache_stats();
GO

-- Opt this routine out of caching regardless of the session setting
SELECT sys.enable_antlr_parse_cache(sys.object_id('dbo.report_proc'), false);
GO
```

## Considerações sobre atualização
<a name="babelfish-procedure-parse-cache-upgrade"></a>
+ O cache de análise do ANTLR está vinculado a uma versão específica do Babelfish. Quando a versão do Babelfish muda, os resultados de análise armazenados em cache deixam de ser reutilizados. As novas execuções analisam novamente a rotina e preenchem o cache automaticamente quando ele está ativado.
+ As rotinas existentes criadas antes das versões 5.7.0 e 6.2.0 são armazenadas em cache na próxima operação de `CREATE` ou `ALTER` ou durante uma execução em uma sessão sem cache previamente preenchido, assim que o cache é ativado.

## Limitações importantes
<a name="babelfish-procedure-parse-cache-limitations"></a>
+ **Padrão DESATIVADO**: o recurso precisa ser ativado explicitamente por sessão (ou forçado por rotina).
+ **Tipo de conexão:** o cache fica ativo somente em conexões **TDS (protocolo do SQL Server)**, não em conexões psql/libpq.
+ **Não armazenados em cache:** **gatilhos, gatilhos de evento e funções de valor de tabela em linha (ITVFs)** não são armazenados em cache nesta versão.
+ **Configuração em todo o cluster:** atualmente, não é possível definir o GUC da sessão por meio de `sp_babelfish_configure`.