

# Uso de la caché de análisis ANTLR en Babelfish
<a name="babelfish-procedure-parse-cache"></a>

A partir de las versiones 5.7.0 y 6.2.0 de Babelfish, puede utilizar una caché de resultados de análisis ANTLR persistente para las rutinas almacenadas de T-SQL (procedimientos y funciones) a fin de reducir la latencia de la primera ejecución.

**Con la caché de análisis de procedimiento:**
+ Las rutinas de T-SQL de gran tamaño (cientos o miles de líneas) ya no suponen una sobrecarga total de análisis de T-SQL en la primera ejecución de cada nueva sesión.
+ El resultado analizado se serializa una vez a la hora del procedimiento/función `CREATE`/`ALTER`, se almacena en el catálogo y se reutiliza en todas las sesiones, lo que emula el comportamiento de almacenamiento en caché de todo el sistema de SQL Server.
+ La característica se controla mediante el GUC `babelfishpg_tsql.enable_antlr_parse_cache` por sesión, con las invalidaciones opcionales por rutina mediante `sys.enable_antlr_parse_cache()`.
+ De forma predeterminada, la característica es **OFF**.

**Rendimiento:** para rutinas de gran tamaño, el análisis ANTLR puede tardar varios segundos. Con la caché de análisis ANTLR, el tiempo de análisis de primera ejecución se reduce a unos pocos milisegundos. Las ejecuciones posteriores en la misma sesión se envían desde la memoria caché de la sesión (submilisegundos) y no se ven afectadas.

## Comprensión de la caché de análisis ANTLR
<a name="babelfish-procedure-parse-cache-overview"></a>

Babelfish debe validar la sintaxis de T-SQL analizando el cuerpo de una rutina la primera vez que se ejecuta en una sesión. Este resultado de análisis normalmente se almacena en caché solo durante la sesión, por lo que cada nueva conexión se vuelve a analizar desde cero. La caché de análisis conserva el resultado del análisis en el catálogo para que las nuevas sesiones puedan reutilizarlo.

Cómo se comporta:
+ **En `CREATE`/`ALTER`:** cuando el almacenamiento en caché está activado, Babelfish analiza la rutina y almacena el resultado del análisis serializado en la caché persistente.
+ **Primera ejecución sin una entrada persistente:** si no existe ninguna entrada en caché (por ejemplo, la rutina se creó antes de activar el almacenamiento en caché), Babelfish realiza el análisis ANTLR normal y rellena la caché persistente.
+ **Primera ejecución en una sesión posterior:** Babelfish carga y deserializa el resultado del análisis en caché en lugar de volver a analizarlo; aquí es donde se ahorra tiempo.
+ **Ejecuciones posteriores en la misma sesión:** servidas desde la memoria caché de la sesión (comportamiento inalterado).
+ Si falta un resultado almacenado en caché o lo creó una versión diferente de Babelfish, Babelfish realiza el análisis ANTLR normal y rellena la caché persistente cuando se habilita el almacenamiento en caché.
+ Si Babelfish encuentra un error al serializar o deserializar un resultado almacenado en caché, la instrucción produce un error y devuelve un error. Desactive el almacenamiento en caché de la rutina afectada y vuelva a intentar la instrucción o vuelva a intentarlo en una nueva sesión con el GUC de caché desactivado. Si el error persiste, póngase en contacto con AWS Support.

## Observación de la mejora del tiempo de análisis
<a name="babelfish-procedure-parse-cache-observing"></a>

Puede medir el efecto con `SET BABELFISH_STATISTICS PROFILE ON`, que informa de `Babelfish T-SQL Batch Parsing Time` a cada lote. En primer lugar, cree un procedimiento grande con el almacenamiento en caché activado para rellenar la caché persistente. A continuación, compare la primera ejecución del procedimiento en dos nuevas sesiones distintas: una con el almacenamiento en caché desactivado, que ignora la entrada persistente, y otra con el almacenamiento en caché activado, que lo reutiliza. Como alternativa, si el almacenamiento en caché no estaba habilitado cuando se creó el procedimiento, ejecútelo en dos nuevas sesiones independientes con el almacenamiento en caché activado: la primera ejecución rellena la caché persistente y la segunda la reutiliza.

En el siguiente ejemplo, cree primero el procedimiento con el almacenamiento en caché activado para rellenar la caché 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
```

A continuación, en una nueva sesión con el almacenamiento en caché desactivado (opción predeterminada), ejecute el procedimiento:

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

El perfil de estadísticas informa de un tiempo de análisis elevado:

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

Por último, en otra sesión nueva con el almacenamiento en caché activado, ejecute el procedimiento:

```
-- 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
```

El perfil de estadísticas informa de un tiempo de análisis significativamente inferior:

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

La primera ejecución de una nueva sesión pasa de unos 20 s de análisis a unos 0,15 s una vez que se vuelve a utilizar el árbol de análisis en caché. Las ejecuciones segunda y posterior en la misma sesión se envían desde la memoria caché de la sesión en ambos casos (submilisegundos) y no se ven afectadas por GUC.

## Habilitación de la caché para una sesión
<a name="babelfish-procedure-parse-cache-enabling"></a>

La función se controla mediante un GUC por sesión (**OFF** de forma predeterminada):

```
-- 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**  
El GUC depende del **ámbito de la sesión** y se restablece al valor predeterminado (OFF) al finalizar la sesión.
Actualmente, este GUC **no** se puede configurar en todo el clúster mediante `sp_babelfish_configure`.

## Control de la caché por rutina
<a name="babelfish-procedure-parse-cache-per-routine"></a>

Puede anular el GUC de sesión para una rutina individual utilizando `sys.enable_antlr_parse_cache`, que acepta el ID de objeto de la rutina:

```
-- 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**  
Debe ser el **propietario** de la rutina o un miembro del rol **sysadmin** para cambiar su configuración de caché.
La configuración por rutina se mantiene en todas las sesiones (se almacena en el catálogo) y se conserva en `ALTER`; se elimina cuando se elimina la rutina.

## Comprobación de estadísticas de la memoria caché
<a name="babelfish-procedure-parse-cache-stats"></a>

`sys.antlr_parse_cache_stats()` devuelve la actividad de la caché de análisis de la sesión actual:

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

En la tabla siguiente, se describe cada columna en la salida.


| Columna | Descripción | 
| --- | --- | 
| cache\_hits | Recuento de ejecuciones rutinarias en las que se reutilizó un resultado de análisis almacenado en caché. | 
| cache\_misses | Recuento de ejecuciones rutinarias para las que se habilitó el almacenamiento en caché pero no se encontró ninguna entrada de caché utilizable. | 
| cache\_writes | Recuento de escrituras correctas en caché persistente. | 
| cache\_evictions | Recuento de entradas almacenadas en caché que se invalidaron o eliminaron (por ejemplo, desconexión automática o conmutador GUC). | 
| cache\_errors | Recuento de errores de serialización o deserialización. | 

Los contadores son por sesión y se restablecen en una conexión nueva.

## Escenario de ejemplo
<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
```

## Consideraciones de actualización
<a name="babelfish-procedure-parse-cache-upgrade"></a>
+ La caché de análisis ANTLR está vinculada a una versión específica de Babelfish. Cuando la versión de Babelfish cambia, los resultados de análisis en caché ya no se reutilizan. Las nuevas ejecuciones vuelven a analizar la rutina y rellenan la caché automáticamente cuando se habilita el almacenamiento en caché.
+ Las rutinas existentes creadas antes de las versiones 5.7.0 y 6.2.0 se almacenan en caché en su siguiente ejecución `CREATE`/`ALTER` o en una sesión en frío una vez que se habilita el almacenamiento en caché.

## Limitaciones importantes
<a name="babelfish-procedure-parse-cache-limitations"></a>
+ **OFF de forma predeterminada:** la característica debe estar habilitada de forma explícita por sesión (o forzada por rutina).
+ **Tipo de conexión:** la caché está activa solo para las conexiones **TDS (protocolo SQL Server)**, no para las conexiones psql/libpq.
+ **No se almacenan en caché:** los **activadores, los activadores de eventos y las funciones integradas con valores de tabla (ITVF)** no se almacenan en caché en esta versión.
+ **Configuración de todo el clúster:** actualmente, el GUC de la sesión no se puede configurar mediante `sp_babelfish_configure`.