DBAtlas · Atlas de operaciones de bases de datos

Gestionar variables bind / parameter sniffing

Oracle

-- Use binds instead of literals (for plan sharing):
SELECT * FROM customer WHERE city = :city;
-- Share legacy code that uses literals:
ALTER SESSION SET cursor_sharing = FORCE;

Las variables bind reducen los hard parses. Adaptive Cursor Sharing mitiga los problemas de sniffing manteniendo varios planes para valores bind con distribuciones sesgadas. Use cursor_sharing=FORCE con cuidado.

PostgreSQL

-- Parameterize with a prepared statement:
PREPARE q (text) AS SELECT * FROM customer WHERE city = $1;
EXECUTE q('Ankara');
-- Set plan cache behavior:
SET plan_cache_mode = force_custom_plan;

plan_cache_mode=auto elige entre planes genéricos y personalizados; force_custom_plan genera un plan específico para los parámetros en cada ejecución (una solución para problemas similares al sniffing).

MySQL

-- Server-side prepared statement:
PREPARE stmt FROM 'SELECT * FROM customer WHERE city = ?';
SET @city = 'Ankara';
EXECUTE stmt USING @city;
DEALLOCATE PREPARE stmt;

Los prepared statements evitan la inyección SQL y reducen el costo de parsing. MySQL también admite la parametrización a nivel de driver.

SQL Server

-- Parameterized query (sp_executesql):
EXEC sp_executesql N'SELECT * FROM dbo.customer WHERE city = @city', N'@city nvarchar(50)', @city = N'Ankara';
-- Handle sniffing with a hint:
SELECT ... OPTION (RECOMPILE);
-- or OPTION (OPTIMIZE FOR (@city = 'Ankara'));

OPTION(RECOMPILE) genera un plan específico para los parámetros en cada ejecución (costoso en CPU). OPTIMIZE FOR fija el plan a un valor concreto/típico; OPTIMIZE FOR UNKNOWN usa la selectividad media.

MongoDB

// The query shape is the key of the plan cache:
db.customer.find({ city: "Ankara" }).explain("queryPlanner")
// Clear a stale plan:
db.customer.getPlanCache().clear()

Las consultas con la misma forma (mismos campos/operadores) comparten el plan cacheado; valores literales distintos no generan un plan nuevo. Si la distribución de valores está muy sesgada, restablézcalo con planCacheClear.

Redis

# Not applicable: there is no query planner or parameter sniffing.

Los comandos se ejecutan directamente; el diseño de claves, no la parametrización, determina el rendimiento.

Elasticsearch

# Reuse the query with a parameterized search template:
POST _scripts/customer_city
{ "script": { "lang": "mustache", "source": { "query": { "term": { "city": "{{city}}" } } } } }
GET <index>/_search/template
{ "id": "customer_city", "params": { "city": "Ankara" } }

Un search template (Mustache) parametriza el cuerpo de la consulta; la aplicación llama a una plantilla fija con valores distintos, lo que mejora la consistencia de las consultas y el uso de la caché.

Abrir en DBAtlas →