“Cada consulta que lanzas contra una base de datos de producción compite por los mismos recursos que sostienen la operación real del negocio. Una SELECT mal planteada no es solo una cuestión de rendimiento: puede traducirse en lentitud para los usuarios, bloqueos en tablas críticas o, en el peor de los casos, una caída del servicio. Estas son las mejores prácticas que aplicamos en Parapentex Studios antes de ejecutar una consulta contra un entorno productivo en Sisense”.
SQL «que funciona» vs. SQL «listo para producción»
SQL («Structured Query Language») sigue siendo, décadas después, una de las herramientas más potentes y más utilizadas para trabajar con datos.
Escribir SQL que funcione es bastante fácil. Escribir SQL que funcione «en producción», sin poner en riesgo el rendimiento del sistema, es otra historia. Que una consulta devuelva el resultado esperado no significa que esté lista para entrar en producción. Ahí entran en juego otros factores: el volumen de datos que mueve, el impacto en otros usuarios conectados de forma concurrente, y si compite por recursos con procesos críticos del negocio.
Y aunque no existe una fórmula mágica, sí hay una serie de hábitos («best practices») que marcan la diferencia entre una consulta segura y un incidente (previsible) en producción. Esto es relevante sea cual sea la arquitectura y el modelo de datos que estés usando en Sisense.
Veamos las opciones disponibles y sus combinaciones.
ElastiCube - la base de datos analítica de alto rendimiento de Sisense
ElastiCube es la base de datos analítica de alto rendimiento de Sisense. Durante el build, Sisense extrae los datos de las fuentes, aplica las transformaciones definidas en el modelo y construye en el ElastiCube una estructura optimizada y comprimida para el análisis. Posteriormente, las consultas de los dashboards se ejecutan contra esta estructura, cargando en memoria los campos necesarios para responder a cada consulta.
En un modelo ElastiCube, el coste de extracción y transformación se concentra principalmente durante el proceso de build, es decir, una consulta SQL ineficiente puede prolongar la construcción del modelo y aumentar la carga sobre los sistemas de origen. Una vez construido el ElastiCube, los dashboards consultan esta base de datos analítica en lugar de acceder directamente a las fuentes.
Para maximizar el rendimiento, las transformaciones estructurales y los cálculos reutilizables deben resolverse, siempre que sea posible, durante el build. En tiempo de consulta se ejecutan principalmente las operaciones que dependen de la interacción del usuario, como filtros, agregaciones dinámicas y cambios en el nivel de análisis. Aunque estas consultas continúan consumiendo recursos de la plataforma, ElastiCube está diseñado para procesarlas de forma eficiente; su rendimiento dependerá también del diseño del modelo, la cardinalidad de los datos, la complejidad analítica y el nivel de concurrencia.
En otras palabras: ElastiCube está optimizado para consultas analíticas interactivas, pero una buena arquitectura debe trasladar al build todo aquello que no necesite calcularse dinámicamente.
Live - consulta directa a la fuente de datos
En un modelo Live, Sisense ejecuta las consultas directamente contra la fuente de datos, sin importar ni almacenar previamente una copia de los datos. Esto permite trabajar con información actualizada, pero hace que el rendimiento del dashboard dependa en gran medida de la capacidad de procesamiento de la base de datos, la eficiencia de las consultas y la concurrencia de usuarios.
En este contexto, las interacciones que requieren recalcular un widget —como aplicar un filtro, realizar un drill o actualizar los datos— pueden generar nuevas consultas contra la fuente. Una consulta ineficiente puede, por tanto, afectar de forma inmediata al tiempo de respuesta del dashboard y al consumo de recursos del sistema de origen.
Para garantizar un rendimiento adecuado, resulta esencial optimizar los filtros, los JOIN y el volumen de datos procesado, así como trasladar a la capa de datos aquellas transformaciones estructurales o cálculos reutilizables que no necesiten resolverse en tiempo de consulta.
Live sobre un Cloud Data Warehouse (CDW)
Cuando la fuente de un modelo Live es un Cloud Data Warehouse (CDW) diseñado para cargas analíticas, el margen de maniobra es mayor gracias a su capacidad de procesamiento y escalabilidad. Sin embargo, el coste computacional —y económico, según el modelo de facturación del proveedor— sigue siendo relevante y puede aumentar a medida que crecen el volumen de datos, la frecuencia de las consultas y la concurrencia de usuarios.
Por ello, optimizar las consultas continúa siendo esencial.
Build to Destination (B2D)
Un modelo Build to Destination (B2D) construye y almacena el modelo de datos en un Cloud Data Warehouse. Una vez publicado, las consultas de los dashboards se comportan como una conexión Live y se ejecutan directamente contra las estructuras generadas en el CDW.
Por tanto, una consulta ineficiente puede afectar de forma inmediata al tiempo de respuesta del dashboard, al consumo de recursos y al coste del proveedor. Además, el propio proceso de build utiliza la capacidad de procesamiento del CDW para crear, cargar y actualizar las tablas de destino. La optimización debe considerar, en consecuencia, tanto las consultas analíticas como la estrategia de construcción y actualización del modelo.
Saber más sobre el modelo B2D
Build to Destination (B2D) es un modelo de datos de Sisense especialmente indicado para organizaciones que ya utilizan ElastiCube, pero necesitan aprovechar la capacidad de almacenamiento y procesamiento de un CDW para gestionar modelos de mayor escala. B2D permite mantener las herramientas de preparación, transformación y modelado de Sisense, utilizando el CDW como destino del modelo y como capa de ejecución de las consultas.
Cómo funciona
En un modelo ElastiCube, el proceso de build importa los datos desde las fuentes, aplica las transformaciones definidas en el modelo y construye una base de datos analítica dentro de la infraestructura de Sisense. En B2D, Sisense utiliza las mismas capacidades de preparación, transformación y modelado, pero genera el modelo directamente en el Cloud Data Warehouse de destino —actualmente Snowflake o Amazon Redshift—. De forma predeterminada, los datos se almacenan en tablas del CDW. Cuando la fuente y el destino pertenecen al mismo warehouse, determinadas tablas también pueden configurarse mediante Create as View, evitando duplicar físicamente los datos existentes.
En el flujo estándar de construcción, Sisense extrae los datos de las fuentes y genera archivos temporales en formato Parquet o CSV, según la configuración. Estos archivos se transfieren a Amazon S3 y, desde allí, se cargan en las tablas del CDW. Una vez completada la importación, los archivos temporales se eliminan. Cuando se aplica la optimización Short Circuit, la transferencia puede realizarse directamente dentro del warehouse, sin generar archivos intermedios ni utilizar S3.
B2D utiliza además dos conexiones diferenciadas con el CDW: una conexión de escritura (Writer), con permisos para crear, cargar y actualizar las tablas durante el proceso de build, y una conexión de lectura (Reader), utilizada para ejecutar las consultas procedentes de los dashboards.
Esta separación facilita el gobierno de los permisos y permite gestionar de forma independiente los recursos destinados a la construcción del modelo y a su explotación analítica.
Por qué se comporta como Live
Una vez construido y publicado el modelo, las consultas se ejecutan directamente contra las estructuras generadas en el CDW. La definición y preparación del modelo continúan gestionándose desde Sisense, pero las interacciones que requieren recalcular los widgets pueden generar consultas contra el warehouse.
Por tanto, el rendimiento depende en gran medida de la capacidad del CDW, del diseño del modelo, de la eficiencia de las consultas y de la concurrencia de usuarios. Estas consultas también consumen recursos de procesamiento y pueden generar costes económicos según el modelo de facturación y la configuración del proveedor.
Comportamientos de actualización propios de B2D
Además de los comportamientos de build aplicables a ElastiCube, B2D incorpora dos opciones específicas para actualizar las tablas del modelo:
- Incremental: incorpora únicamente los registros nuevos identificados desde el último build mediante una columna de referencia, normalmente una fecha o un identificador incremental.
- Upsert (Update or Insert): actualiza los registros existentes e inserta los nuevos utilizando una clave única para identificar cada fila.
Estas estrategias pueden reducir el volumen de datos que debe procesarse en cada actualización frente a una reconstrucción completa. Sin embargo, su configuración debe responder correctamente a la lógica de actualización de los datos. Una clave inadecuada, una columna incremental mal seleccionada o un volumen elevado de actualizaciones pueden incrementar la duración y el consumo de recursos del build.
Cuándo tiene sentido usar B2D
- Un modelo ElastiCube ha crecido hasta requerir una capacidad de almacenamiento o procesamiento superior.
- La organización quiere conservar las capacidades de modelado y transformación de Sisense, pero ejecutar y almacenar el modelo en un CDW.
- Se necesita una estrategia de actualización mediante Upsert o una gestión incremental adaptada a grandes volúmenes de datos.
- Los equipos de datos o los data modelers necesitan preparar y materializar modelos analíticos sobre Snowflake o Redshift desde la interfaz de Sisense.
- La organización ya dispone de un CDW compatible y quiere utilizarlo como capa central de almacenamiento y consulta, evitando mantener el modelo analítico dentro de la infraestructura de Sisense.
- Existen necesidades de escalabilidad, gobierno o separación entre los recursos destinados al build y los utilizados por los dashboards.
A tener en cuenta
B2D combina dos tipos de consumo en el Cloud Data Warehouse. Por una parte, el proceso de build utiliza capacidad de procesamiento para crear, cargar y actualizar las tablas del modelo. Por otra, una vez publicado, las consultas de los dashboards se ejecutan contra esas tablas de forma equivalente a una conexión Live.
Por ello, una consulta ineficiente puede afectar inmediatamente al tiempo de respuesta de los dashboards y al consumo de recursos del CDW. Del mismo modo, una estrategia de build mal configurada puede incrementar la duración y el coste de las actualizaciones del modelo. La optimización debe abordar ambos planos por separado: la construcción y actualización de las tablas, y las consultas analíticas ejecutadas durante el uso de los dashboards.
Modelo Híbrido
En un modelo híbrido, un mismo dashboard combina widgets construidos sobre modelos ElastiCube y Live. Cada widget conserva el comportamiento y las implicaciones de rendimiento de su fuente: los widgets basados en ElastiCube consultan la estructura almacenada en Sisense, mientras que los widgets Live ejecutan las consultas directamente contra el sistema de origen.
Por tanto, las interacciones que recalculan varios widgets —como la aplicación de un filtro compartido— pueden generar simultáneamente consultas contra ElastiCube y contra la fuente Live. La optimización debe analizarse de forma independiente para cada modelo y tener en cuenta el rendimiento conjunto del dashboard.
Saber más sobre el modelo híbrido
El modelo híbrido es una estrategia de diseño que permite combinar en un mismo dashboard widgets basados en diferentes modelos de datos, principalmente ElastiCube y Live.
No constituye un motor de almacenamiento o ejecución independiente, sino una forma de asignar a cada conjunto de widgets la fuente y el comportamiento que mejor responden a sus necesidades de actualidad, rendimiento y análisis.
Cómo funciona
En un dashboard híbrido, algunos widgets consultan un ElastiCube, donde los datos han sido previamente importados, transformados y almacenados mediante un proceso de build. La actualidad de estos widgets depende, por tanto, de la frecuencia con la que se actualiza el modelo.
Otros widgets dentro del mismo dashboard utilizan un modelo Live y ejecutan sus consultas directamente contra la fuente de datos. Esto permite trabajar con información cercana al tiempo real, aunque el rendimiento depende en gran medida de la capacidad de la fuente, de la eficiencia de las consultas, de la concurrencia y de los mecanismos de caché aplicables.
Los widgets de cada fuente operan de forma independiente dentro del dashboard. No obstante, Sisense permite aplicar filtros a widgets basados en diferentes fuentes cuando las tablas y columnas correspondientes están definidas con nombres compatibles.
Patrones de uso habituales
Un modelo híbrido permite asignar cada conjunto de datos al mecanismo de acceso más adecuado, con independencia de que la información sea histórica o reciente.
ElastiCube puede utilizarse cuando los datos requieren integración, transformación, estandarización o preparación previa, o cuando se busca una capa analítica optimizada que reduzca la carga sobre los sistemas de origen. Por ejemplo, puede consolidar información procedente de varias aplicaciones, aplicar reglas de negocio y generar métricas reutilizables para distintos dashboards.
Live puede utilizarse tanto para datos actuales como históricos. Un histórico de cinco o diez años no necesita almacenarse necesariamente en un ElastiCube: cuando permanece disponible en una base de datos o un Cloud Data Warehouse gobernado y preparado para cargas analíticas, puede consultarse directamente desde su fuente. Esto evita crear una copia adicional, aunque el rendimiento y el coste dependerán del volumen procesado, del diseño de las consultas y de la capacidad de la plataforma de datos.
Por tanto, un dashboard híbrido podría combinar una capa preparada en ElastiCube con datos operativos o históricos consultados mediante Live. La elección debe basarse en las necesidades de transformación, actualización, rendimiento, gobierno, coste y carga sobre los sistemas de origen, y no únicamente en la antigüedad de los datos.
Más allá del número de fuentes
Un dashboard híbrido puede incorporar varios modelos y fuentes de datos. Sin embargo, el número de fuentes no determina por sí solo su comportamiento. Cada una puede tener diferentes niveles de latencia, disponibilidad, concurrencia, capacidad de procesamiento y coste.
Para analizar correctamente el rendimiento conviene distinguir dos dimensiones:
- Dónde se preparan y almacenan los datos: en ElastiCube, en las tablas originales de una fuente Live o en las tablas generadas mediante B2D.
- Dónde se ejecutan las consultas del dashboard: en el motor ElastiCube o en un sistema externo, como una base de datos o un Cloud Data Warehouse.
Esta distinción es especialmente importante en B2D, porque el modelo se construye o define en el CDW durante el build, mientras que las consultas del dashboard se ejecutan posteriormente contra ese CDW.
Implicaciones para la optimización
Un dashboard híbrido combina diferentes patrones de ejecución según la fuente utilizada por cada widget.
En los modelos ElastiCube, una consulta SQL ineficiente durante la extracción o transformación puede prolongar el build y aumentar la carga sobre los sistemas de origen. Una vez construido el modelo, las consultas de los dashboards se ejecutan contra ElastiCube y consumen recursos de la plataforma Sisense, aunque ya no acceden directamente a las fuentes originales.
En los modelos Live, las consultas se ejecutan contra la fuente y pueden afectar inmediatamente al tiempo de respuesta, al consumo de recursos y, cuando se utiliza un CDW, al coste económico.
En B2D deben considerarse ambos planos: el consumo asociado al build y actualización de las tablas en el CDW, y el correspondiente a las consultas analíticas ejecutadas contra esas tablas.
Por ello, la optimización debe realizarse identificando primero la fuente de cada widget y su mecanismo de ejecución, en lugar de aplicar las mismas recomendaciones de forma uniforme a todo el dashboard.
Cuándo tiene sentido usarlo
Un modelo híbrido puede resultar adecuado cuando:
- Un mismo dashboard combina información con diferentes requisitos de actualización.
- Determinados análisis se benefician de la preparación y el rendimiento de ElastiCube, mientras que otros necesitan consultar directamente una fuente actualizada.
- Se requieren vistas agregadas junto con detalle transaccional.
- El coste, la disponibilidad o el rendimiento hacen que no resulte conveniente ejecutar todas las consultas contra una única fuente.
- Las necesidades analíticas varían entre widgets y no justifican imponer un único modelo de ejecución a todo el dashboard.
A tener en cuenta
Un dashboard híbrido combina varias rutas de ejecución bajo una misma interfaz. Esto exige identificar, para cada widget, qué fuente utiliza, dónde se procesan sus consultas, con qué frecuencia se actualizan sus datos y qué recursos consume.
También deben revisarse cuidadosamente los filtros compartidos, la coherencia de las definiciones entre modelos, la disponibilidad de las fuentes Live y la experiencia global del dashboard, ya que una fuente con mayor latencia puede condicionar el tiempo de respuesta percibido aunque el resto de los widgets funcionen correctamente.
Un denominador común: el SQL importa en todas las arquitecturas
En todos estos escenarios, los principios de optimización SQL siguen siendo aplicables, aunque el dialecto, el plan de ejecución y el impacto de cada consulta dependan del motor y de la arquitectura utilizada. Las malas prácticas terminan manifestándose de una forma u otra: en la duración o el fallo de un build, en el rendimiento y la disponibilidad del dashboard, en la carga sobre los sistemas de origen o en el coste de procesamiento del Cloud Data Warehouse.
La buena noticia es que gran parte de estos riesgos puede anticiparse mediante un conjunto de prácticas ampliamente conocidas, tanto al diseñar las consultas de extracción y transformación como al construir los modelos y dashboards que generarán consultas en tiempo de análisis.
En Parapentex Studios nos encontramos con cierta frecuencia con este escenario en proyectos de modelado y analítica embebida con Sisense: los usuarios necesitan respuestas rápidas, pero la infraestructura que las proporciona —ya sea ElastiCube, una fuente Live o un modelo B2D sobre un CDW— no puede permitirse consultas ni modelos diseñados de forma descuidada.
Este riesgo es especialmente relevante en entornos de autoservicio, donde usuarios con diferentes niveles de conocimiento técnico pueden crear relaciones incorrectas, dependencias circulares, JOIN que multiplican el volumen de datos o cálculos excesivamente costosos. Un diseño inadecuado puede degradar el rendimiento, bloquear procesos de construcción, saturar los recursos disponibles o incluso comprometer temporalmente la estabilidad del sistema.
En este post repasamos nueve prácticas concretas, acompañadas de ejemplos, que te ayudarán a diseñar y optimizar las consultas antes de llevarlas a un entorno de producción en Sisense.
Antes de entrar en el detalle de cada práctica, esta tabla resume su impacto principal según el modelo de datos utilizado en Sisense.

Las 9 prácticas para escribir SQL preparado para producción
Los ejemplos que se incluyen en las nueve prácticas que veremos a continuación utilizan sintaxis SQL común y ampliamente compatible. Algunos elementos —como los literales de fecha, la limitación de filas o las herramientas de análisis del plan— pueden requerir adaptación según el motor conectado a Sisense.
(1) - Parte siempre de un requisito de negocio claro
Ya hemos hablado en otros posts de cómo definir bien los requisitos de negocio en proyectos de analítica. Esas mismas prácticas se vuelven aún más importantes cuando el destino final es una consulta SQL contra un entorno de producción.
Una consulta eficiente comienza antes de escribir la primera línea de SQL. Si no está claro qué decisión debe soportar, quién utilizará el resultado y qué nivel de detalle necesita, es fácil terminar procesando más tablas, columnas y registros de los necesarios. En Sisense, esta definición inicial también condiciona el diseño del modelo, la granularidad de los datos y la elección entre ElastiCube, Live, B2D o una arquitectura híbrida.
Identifica a los interlocutores relevantes
Antes de diseñar la consulta, involucra tanto a los responsables del caso de uso como a los propietarios de la plataforma de datos. Según la arquitectura, esto puede incluir al usuario de negocio, al data modeler de Sisense, al equipo de datos, al DBA o al responsable del Cloud Data Warehouse.
Su participación permite validar la semántica de los datos, conocer las restricciones de la fuente y anticipar el impacto que tendrá la consulta sobre el rendimiento, la concurrencia y el coste.
Define la decisión o el resultado esperado
No empieces por las tablas disponibles, sino por las preguntas que deben responderse:
- ¿Qué decisión se tomará con este análisis?
- ¿Qué indicadores son realmente necesarios?
- ¿Qué dimensiones permitirán interpretar esos indicadores?
- ¿Qué nivel de detalle necesita el usuario?
Un caso de uso bien delimitado evita incorporar información «por si acaso», duplicar informes existentes o construir consultas excesivamente amplias que después resultan difíciles de mantener y optimizar.
Determina la granularidad correcta
Define qué representa exactamente cada fila del resultado: una venta, un cliente, un pedido, una operación diaria o una agregación mensual.
Una granularidad mal definida puede producir duplicidades, JOIN incorrectos y agregaciones inconsistentes. También puede obligar al motor a procesar millones de registros cuando el análisis solo necesita resultados agregados.
Establece los requisitos operativos
Además del contenido funcional, documenta las condiciones bajo las que se ejecutará la consulta:
- Volumen aproximado de datos.
- Frecuencia de actualización.
- Latencia o tiempo de respuesta esperado.
- Número estimado de usuarios concurrentes.
- Filtros y recorridos de drill necesarios.
- Reglas de seguridad y segmentación del dato.
- Fuente de verdad y modelo de ejecución.
- Impacto admisible sobre la base de datos o el CDW.
Estas variables ayudan a determinar si la información debe prepararse durante un build, consultarse mediante Live o materializarse mediante B2D.
Plantea las preguntas adecuadas
Las preguntas clásicas —quién, qué, dónde, cuándo y por qué— siguen siendo útiles, pero en analítica conviene añadir dos más:
- ¿Cómo se calculará y utilizará el resultado?
- ¿Con qué frecuencia se ejecutará o actualizará?
Si estas preguntas no tienen respuestas precisas, probablemente el requisito todavía no está suficientemente definido para convertirse en una consulta de producción.
Confirma los criterios de aceptación
Antes de implementar la consulta, valida con los interlocutores:
- El resultado esperado.
- Las métricas y sus definiciones.
- La granularidad.
- Los filtros necesarios.
- La frecuencia de actualización.
- El tiempo de respuesta aceptable.
- La reconciliación con la fuente de verdad.
Una consulta no está correctamente diseñada solo porque se ejecuta sin errores. También debe devolver el resultado esperado, hacerlo con un coste razonable y mantener un comportamiento estable cuando aumenten el volumen de datos y la concurrencia.
Este trabajo previo evita procesar información innecesaria, reduce la complejidad del modelo y permite elegir correctamente entre ElastiCube, Live, B2D o una arquitectura híbrida. Cuanto más claro sea el requisito de negocio, más sencillo será construir una consulta correcta, mantenible y preparada para producción.
Elegir la arquitectura equivocada porque el requisito no estaba claro no es un error que se corrija con una consulta mejor: implica rediseñar el modelo o migrar entre ElastiCube, Live y B2D.
(2) - Selecciona únicamente las columnas que necesitas
“SELECT *” es una forma rápida de explorar el contenido de una tabla, pero no debería utilizarse de forma habitual en consultas de producción. Al devolver todas las columnas disponibles, puede obligar al motor a procesar y transferir datos que el análisis no necesita, además de aumentar la complejidad del modelo y su dependencia del esquema de origen.
EVITAR
Por ejemplo, si el requisito consiste en obtener las direcciones postales de los clientes, esta consulta devuelve toda la información almacenada en la tabla.
SELECT * FROM Customers;
El resultado podría incluir teléfonos, observaciones, fechas de actividad, atributos comerciales o campos sensibles que no forman parte del caso de uso.
BUENA PRÁCTICA
Es preferible seleccionar expresamente los campos necesarios:
SELECT
CustomerID,
FirstName,
LastName,
Address,
City,
State,
PostalCode,
Country
FROM Customers;
Esta práctica mejora la legibilidad, limita el volumen de datos procesado y reduce el riesgo de incorporar información innecesaria. También mantiene estable el contrato de la consulta: si la tabla de origen añade nuevas columnas, estas no se incluirán automáticamente en el modelo o en el resultado.
Impacto en Sisense
En un modelo ElastiCube, importar columnas que no se utilizarán puede aumentar el volumen extraído desde las fuentes, prolongar el build y consumir almacenamiento adicional. En Live, las columnas seleccionadas forman parte de las consultas ejecutadas contra la fuente. Reducirlas puede disminuir el volumen procesado y transferido, especialmente cuando el sistema subyacente es una plataforma columnar o un Cloud Data Warehouse. En B2D, seleccionar únicamente los campos necesarios ayuda a reducir tanto el trabajo realizado durante la construcción y materialización del modelo como el tamaño y la complejidad de las tablas generadas en el CDW.
Por tanto, antes de incorporar un campo, comprueba que responde a un requisito funcional, técnico, de seguridad o de relación dentro del modelo. Si no cumple ninguna de estas funciones, probablemente no debería formar parte de la consulta.
(3) - No utilices DISTINCT para ocultar duplicidades
DISTINCT es una funcionalidad legítima de SQL cuando el objetivo consiste en obtener una lista de valores o combinaciones únicas. Antes de utilizarlo, identifica qué representa cada fila, cuál es el origen de las duplicidades y qué resultado requiere realmente el análisis.
EVITAR
Caso 1. Ocultar la multiplicación causada por un JOIN: Una relación uno a muchos (1-M) puede generar varias filas por cada registro de la tabla principal.
SELECT DISTINCT
c.CustomerID,
c.FirstName,
c.LastName
FROM Customers c
INNER JOIN Orders o
ON c.CustomerID = o.CustomerID;
En este caso DISTINCT elimina las repeticiones, pero oculta que la multiplicación de filas procede de la relación entre clientes y pedidos. Antes de eliminar esas filas, debe determinarse si el objetivo consiste en comprobar la existencia de pedidos o en calcular información agregada sobre ellos.
Por tanto, no debe evitarse DISTINCT por ser incorrecto, sino su uso automático para compensar una multiplicación de filas cuyo origen y propósito no se han analizado.
Caso 2. Intentar corregir una granularidad mal definida: DISTINCT determina la unicidad a partir de la combinación completa de las columnas seleccionadas:
SELECT DISTINCT
FirstName,
LastName,
Address
FROM Customers;
Dos clientes diferentes podrían compartir nombre, apellido y dirección. En ese caso, la consulta los presentaría como una sola fila, aunque sean entidades distintas. También debe evitarse utilizar GROUP BY con todas las columnas únicamente para eliminar registros repetidos:
SELECT
CustomerID,
FirstName,
LastName,
Address
FROM Customers
GROUP BY
CustomerID,
FirstName,
LastName,
Address;
Si no existe ninguna agregación, GROUP BY actúa únicamente como sustituto de DISTINCT y no permite comprender ni corregir el origen de las duplicidades.
BUENA PRÁCTICA
Caso 1. Define correctamente la granularidad: si el resultado debe representar clientes individuales, incluye la clave que identifica de forma única a cada cliente:
SELECT
CustomerID,
FirstName,
LastName,
Address
FROM Customers;
Ten en cuenta que incluir CustomerID no elimina una duplicidad: define correctamente la granularidad del resultado, pues cada fila representa un cliente único, aunque dos clientes compartan nombre, apellido o dirección.
Otra opción es utilizar EXISTS para comprobar relaciones: si el requisito consiste únicamente en obtener los clientes que tienen al menos un pedido, utiliza EXISTS:
SELECT
c.CustomerID,
c.FirstName,
c.LastName
FROM Customers c
WHERE EXISTS (
SELECT 1
FROM Orders o
WHERE o.CustomerID = c.CustomerID
);
Esta consulta expresa directamente la condición de negocio y evita multiplicar las filas de clientes por el número de pedidos relacionados.
Caso 2. Utilizar GROUP BY para calcular agregaciones: si el objetivo es calcular información agregada —por ejemplo, el número de pedidos por cliente—, debe utilizarse GROUP BY:
SELECT
c.CustomerID,
c.FirstName,
c.LastName,
COUNT(o.OrderID) AS NumberOfOrders
FROM Customers c
INNER JOIN Orders o
ON c.CustomerID = o.CustomerID
GROUP BY
c.CustomerID,
c.FirstName,
c.LastName;
En este caso, la agrupación responde al requisito funcional: cada fila representa un cliente y contiene una métrica calculada sobre sus pedidos.
Caso 3. Utilizar DISTINCT para obtener valores únicos: cuando la unicidad forma parte explícita del resultado esperado, DISTINCT es lo adecuado. Por ejemplo, para conocer los países en los que existen clientes registrados, su uso es correcto porque el requisito consiste en obtener una sola fila por país.
SELECT DISTINCT
Country
FROM Customers;
Antes de utilizar DISTINCT, determina qué entidad representa cada fila y qué operación responde realmente al requisito:
EXISTS, para comprobar si existen registros relacionados.GROUP BY, para agrupar datos y calcular métricas.DISTINCT, para obtener valores o combinaciones únicas.
Impacto en Sisense
En ElastiCube, un DISTINCT aplicado durante la extracción o transformación puede aumentar el trabajo del build y ocultar problemas de relaciones o granularidad dentro del modelo.
En Live, la eliminación de duplicados se ejecuta contra la fuente y puede afectar al tiempo de respuesta y al consumo de recursos, especialmente sobre grandes volúmenes de datos.
En B2D, el coste puede aparecer tanto durante la construcción de las tablas en el CDW como en las consultas ejecutadas posteriormente contra el modelo.
Utiliza DISTINCT cuando la unicidad sea una condición funcional del resultado, no como una forma de ocultar problemas de modelado, cardinalidad o diseño de los JOIN.
(4) - Declara los JOIN de forma explícita
SQL permite relacionar tablas utilizando una sintaxis implícita, en la que las tablas se enumeran separadas por comas y la condición de unión se incluye en la cláusula WHERE.
Cuando una consulta combina varias tablas, las condiciones que las relacionan deben quedar claramente definidas. Utilizar la sintaxis JOIN ... ON permite separar las relaciones entre tablas de los filtros aplicados al resultado, mejora la legibilidad y reduce el riesgo de generar accidentalmente un producto cartesiano.
EVITAR
Evita siempre definir las relaciones en la cláusula WHERE:
SELECT
c.CustomerID,
c.Name,
s.LastSaleDate
FROM Customers c, Sales s
WHERE c.CustomerID = s.CustomerID
AND s.Status = 'Closed';
Aunque esta sintaxis puede devolver el resultado esperado, mezcla en la misma cláusula las condiciones de unión y los filtros de negocio. A medida que se incorporan más tablas y condiciones, resulta más difícil comprobar que todas las relaciones necesarias están correctamente definidas.
El riesgo aparece cuando una condición de unión se omite o se especifica de forma incorrecta:
SELECT
c.CustomerID,
c.Name,
s.LastSaleDate
FROM Customers c, Sales s
WHERE s.Status = 'Closed';
Al no existir una condición que relacione Customers con Sales, la consulta genera un producto cartesiano: cada cliente se combina con todas las ventas que cumplen el filtro.
El número de filas resultante puede crecer de forma multiplicativa. Si una tabla contiene 1.000 clientes y la otra 10.000 ventas, el cruce podría generar hasta 10 millones de combinaciones antes de completar el procesamiento. Esto puede provocar resultados incorrectos, tiempos de ejecución muy elevados, agotamiento de recursos e incluso afectar a la estabilidad del sistema.
BUENA PRÁCTICA
La buena práctica es utilizar JOIN ... ON:
SELECT
c.CustomerID,
c.Name,
s.LastSaleDate
FROM Customers c
INNER JOIN Sales s
ON c.CustomerID = s.CustomerID
WHERE s.Status = 'Closed';
La sintaxis explícita permite distinguir claramente:
ON, para definir cómo se relacionan las tablas.WHERE, para determinar qué filas deben conservarse.
Esta separación facilita la revisión de la consulta, permite detectar relaciones ausentes y reduce el riesgo de introducir cruces accidentales cuando se añaden nuevas tablas o filtros.
También hace explícito el tipo de relación requerido:
INNER JOIN, cuando solo deben conservarse los registros coincidentes.LEFT JOIN, cuando deben mantenerse todos los registros de la tabla izquierda.RIGHT JOIN, cuando deben mantenerse todos los registros de la tabla derecha.FULL JOIN, cuando deben conservarse los registros de ambas tablas, exista o no correspondencia.
En los outer joins, colocar una condición en ON o en WHERE puede modificar el resultado. Por ello, es especialmente importante separar correctamente las condiciones de relación de los filtros posteriores.
Otra opción es utilizar CROSS JOIN cuando el producto cartesiano sea intencionado. Un producto cartesiano puede responder a un requisito válido, por ejemplo, para generar todas las combinaciones posibles entre fechas y regiones:
SELECT
d.CalendarDate,
r.RegionName
FROM CalendarDates d
CROSS JOIN Regions r;
Cuando este comportamiento sea deliberado, utiliza CROSS JOIN de forma explícita. Así queda claro que la multiplicación de filas forma parte del diseño y no procede de una condición de unión olvidada.
Impacto en Sisense
En un modelo ElastiCube, un JOIN incorrecto durante la extracción o transformación puede multiplicar el volumen de datos procesado, prolongar o hacer fallar el build y generar estructuras mucho mayores de lo previsto.
En Live o B2D, un producto cartesiano accidental puede afectar inmediatamente al tiempo de respuesta de los dashboards, saturar los recursos de la fuente y, en un Cloud Data Warehouse, incrementar de forma considerable el coste computacional.
El mismo riesgo existe en las relaciones definidas visualmente en el modelo de Sisense. Una columna de unión incorrecta, una ruta ambigua o una relación muchos a muchos (M-M) no prevista puede multiplicar registros, distorsionar las métricas y comprometer el rendimiento o la estabilidad del sistema.
Utiliza relaciones explícitas, valida la cardinalidad y comprueba siempre el volumen y la granularidad esperados antes de llevar una consulta o un modelo a producción.
(5) - Filtra filas con WHERE y grupos con HAVING
Cuando una consulta incluye agregaciones, es importante aplicar cada condición en la fase adecuada.
WHERE filtra las filas antes de que el motor ejecute el GROUP BY y calcule las agregaciones. HAVING, en cambio, filtra los grupos resultantes después de realizar cálculos como COUNT, SUM o AVG.
Aplicar los filtros en el lugar correcto expresa mejor la intención de la consulta y puede reducir el volumen de datos que debe agruparse y procesarse.
EVITAR
Evita utilizar HAVING para filtrar filas individuales. Supongamos que queremos analizar las ventas realizadas durante 2026. El intervalo temporal debe aplicarse antes de agrupar los registros:
SELECT
c.CustomerID,
c.Name,
COUNT(s.SalesID) AS NumberOfSales
FROM Customers c
INNER JOIN Sales s
ON c.CustomerID = s.CustomerID
GROUP BY
c.CustomerID,
c.Name
HAVING s.SaleDate >= DATE '2026-01-01'
AND s.SaleDate < DATE '2027-01-01';
Esta formulación no es adecuada porque “SaleDate” representa una condición sobre las filas individuales de ventas, no sobre el resultado de la agregación. Además, al no formar parte del GROUP BY ni estar agregada, la expresión no será válida en muchos motores SQL.
Evita utilizar HAVING como sustituto general de WHERE. Es cierto que algunos motores pueden reescribir internamente ciertas condiciones de HAVING —sobre todo cuando hacen referencia a columnas de agrupación— y aplicarlas como si fueran un filtro de WHERE durante la optimización. Pero esta capacidad del optimizador no debe condicionar cómo escribes la consulta: no todos los motores lo hacen, y el comportamiento puede variar según la versión o la configuración. Expresa cada condición según su función:
- Utiliza
WHEREpara decidir qué filas entran en la agregación. - Utiliza
HAVINGpara decidir qué grupos permanecen después de calcularla.
Esta separación mejora la legibilidad, facilita el mantenimiento y evita procesar innecesariamente datos que podrían haberse descartado antes.
BUENA PRÁCTICA
La buena práctica para nuestro ejemplo sería aplicar el filtro de filas con WHERE:
SELECT
c.CustomerID,
c.Name,
COUNT(s.SalesID) AS NumberOfSales
FROM Customers c
INNER JOIN Sales s
ON c.CustomerID = s.CustomerID
WHERE s.SaleDate >= DATE '2026-01-01'
AND s.SaleDate < DATE '2027-01-01'
GROUP BY
c.CustomerID,
c.Name;
El motor filtra primero las ventas correspondientes a 2026 y agrupa únicamente las filas que cumplen esa condición. Esto evita incorporar a la agregación registros que posteriormente no formarán parte del resultado.
Cuando la condición depende de un resultado agregado, utiliza HAVING para filtrar resultados agregados. Si el requisito consiste en obtener únicamente los clientes que realizaron al menos diez ventas durante 2026, deben utilizarse ambas cláusulas:
SELECT
c.CustomerID,
c.Name,
COUNT(s.SalesID) AS NumberOfSales
FROM Customers c
INNER JOIN Sales s
ON c.CustomerID = s.CustomerID
WHERE s.SaleDate >= DATE '2026-01-01'
AND s.SaleDate < DATE '2027-01-01'
GROUP BY
c.CustomerID,
c.Name
HAVING COUNT(s.SalesID) >= 10;
En esta consulta:
WHEREselecciona las ventas realizadas durante 2026.GROUP BYagrupa esas ventas por cliente.HAVINGconserva únicamente los clientes cuyo número de ventas es igual o superior a diez.
Impacto en Sisense
En un modelo ElastiCube, aplicar correctamente los filtros en una consulta de extracción o transformación puede reducir el volumen procesado durante el build y evitar agregaciones innecesarias sobre los sistemas de origen.
En Live, los filtros y agregaciones se ejecutan directamente contra la fuente. Una consulta que agrupa más filas de las necesarias puede aumentar el tiempo de respuesta del dashboard y el consumo de recursos de la base de datos.
En B2D, este principio debe considerarse tanto durante la construcción de las tablas en el CDW como en las consultas ejecutadas posteriormente contra el modelo publicado.
Aplica los filtros lo antes posible siempre que no alteres el significado del cálculo. WHERE reduce las filas de entrada; HAVING selecciona los resultados agregados.
(6) - Evita los comodines iniciales cuando no sean necesarios
Los operadores de búsqueda de patrones permiten localizar texto sin exigir una coincidencia exacta. Sin embargo, la posición de los comodines modifica tanto el significado de la consulta como su posible coste de ejecución.
Antes de escribir el patrón, determina qué tipo de búsqueda necesita realmente el usuario:
- Valores que empiezan por una cadena.
- Valores que terminan en una cadena.
- Valores que contienen una cadena en cualquier posición.
EVITAR
Se debe evitar buscar en cualquier posición cuando el requisito es «empieza por». Supongamos que queremos obtener las ciudades cuyo nombre empieza por “Char”:
SELECT
City
FROM Customers
WHERE City LIKE '%Char%';
El comodín situado al principio indica que puede existir cualquier texto antes de “Char”. Por tanto, la consulta no busca únicamente ciudades que comiencen por esa cadena, sino cualquier valor que la contenga en alguna posición. Además de resultados como “Charleston”, “Charlotte” o “Charlton”, podría devolver nombres como “Cape Charles”, “Crab Orchard” o cualquier otro valor que contenga la cadena “Char” en su interior.
Esta búsqueda suele exigir examinar una parte mucho mayor de los datos y, en condiciones normales, dificulta el aprovechamiento de un índice B-tree convencional.
BUENA PRÁCTICA
Cuando el requisito sea encontrar valores que empiezan por una cadena, coloca el comodín únicamente al final:
SELECT
City
FROM Customers
WHERE City LIKE 'Char%';
Esta expresión representa correctamente la intención de la consulta: el valor debe comenzar por “Char”, aunque pueda contener cualquier texto a continuación. Además de ser más precisa, una búsqueda por prefijo puede permitir que el motor utilice índices u otros mecanismos de acceso optimizado, dependiendo de la base de datos, el tipo de índice y la configuración de ordenación o collation.
¿Cuándo el comodín inicial sí es necesario? Una búsqueda con comodín inicial no es incorrecta cuando el requisito consiste realmente en localizar una cadena en cualquier posición:
SELECT
City
FROM Customers
WHERE City LIKE '%Charles%';
En este caso, eliminar el primer comodín cambiaría el significado funcional de la consulta. La solución no consiste en reescribirla como una búsqueda por prefijo, sino en evaluar si la plataforma dispone de mecanismos específicos para búsquedas de texto o subcadenas, como índices especializados, búsqueda de texto completo o servicios de optimización.
Si este tipo de búsqueda se ejecuta con frecuencia sobre grandes volúmenes de datos, debe revisarse con el responsable de la plataforma y validarse mediante el plan de ejecución.
Impacto en Sisense
En un modelo ElastiCube, un patrón con comodín inicial utilizado durante la extracción o transformación puede incrementar el trabajo realizado por la fuente y prolongar el build. Una vez construido el modelo, las búsquedas realizadas por los dashboards consumen recursos del motor ElastiCube.
En Live, estas búsquedas se ejecutan directamente contra la fuente cuando una interacción requiere recalcular el widget. Si se aplican sobre columnas extensas, grandes volúmenes o filtros utilizados por muchos usuarios, pueden incrementar significativamente el tiempo de respuesta y la carga del sistema de origen.
En B2D, el impacto puede producirse tanto durante la construcción de las tablas como en las consultas posteriores ejecutadas contra el CDW. Dependiendo del proveedor, estas búsquedas también pueden aumentar el consumo computacional y el coste económico.
Utiliza patrones de prefijo cuando el requisito sea «empieza por». Reserva los comodines iniciales para búsquedas que realmente necesiten localizar una cadena en cualquier posición y, en esos casos, evalúa mecanismos especializados de búsqueda y optimización.
(7) - Prueba con un subconjunto antes de escalar
Antes de ejecutar una consulta compleja sobre todo el volumen de datos, valida su lógica con un subconjunto reducido y controlado. Esto permite detectar errores en los filtros, las relaciones, la granularidad y los cálculos antes de comprometer todos los recursos del entorno.
Limitar las filas devueltas puede facilitar esta validación, pero no garantiza que el motor reduzca en la misma proporción el trabajo realizado.
EVITAR
Debes evitar confiar únicamente en “LIMIT”:
SELECT
CustomerID,
COUNT(*) AS NumberOfSales
FROM Sales
WHERE SaleDate >= DATE '2026-01-01'
GROUP BY
CustomerID
LIMIT 10;
Esta consulta devuelve únicamente diez filas, pero el límite se aplica después del filtro y de la agregación. Para calcular el número de pedidos por cliente, el motor puede tener que procesar todas las filas que cumplen la condición y construir todos los grupos antes de limitar el resultado. Por tanto, LIMIT puede reducir el volumen de información transferido y mostrado, pero no debe interpretarse como una garantía de menor consumo computacional.
Además, sin una cláusula ORDER BY, los diez registros devueltos no siguen un orden determinado y pueden variar entre ejecuciones. Si necesitas comprobar un resultado concreto o reproducible, debes establecer expresamente el criterio de ordenación.
Ten en cuenta que LIMIT no equivale a una muestra representativa: LIMIT 10 devuelve diez filas del resultado, pero no garantiza que constituyan una muestra aleatoria o representativa del conjunto completo.
Si el objetivo es validar únicamente la estructura y el contenido de la consulta, un subconjunto controlado puede ser suficiente. Si necesitas realizar una prueba estadística o evaluar la distribución real de los datos, utiliza los mecanismos de muestreo disponibles en el motor de origen y comprueba su sintaxis y comportamiento específico.
BUENA PRÁCTICA
En nuestro caso, la buena práctica consiste en reducir el conjunto de entrada. Para validar la consulta, acota primero los datos que entrarán en las operaciones más costosas. Puedes utilizar un intervalo temporal reducido, un rango de identificadores, una región, un cliente o cualquier otro criterio controlado y representativo del caso de uso.
SELECT
CustomerID,
COUNT(*) AS NumberOfSales
FROM Sales
WHERE SaleDate >= DATE '2026-01-01'
AND SaleDate < DATE '2026-01-08'
GROUP BY
CustomerID
ORDER BY
NumberOfSales DESC,
CustomerID
LIMIT 10;
En este ejemplo, la consulta se valida inicialmente sobre una semana de datos. El motor agrega un conjunto de entrada más reducido y devuelve un resultado ordenado y reproducible. Una vez comprobada la lógica, amplía progresivamente el periodo o el volumen procesado y revisa cómo evoluciona el plan de ejecución, la duración y el consumo de recursos.
¿Cuándo puede reducir realmente el trabajo? En consultas sencillas, sin agregaciones ni ordenaciones costosas, un límite puede permitir que el motor detenga la ejecución después de encontrar las filas necesarias:
SELECT
SalesID,
CustomerID,
DaleDate,
TotalAmount
FROM Sales
WHERE SaleDate >= DATE '2026-01-01'
ORDER BY
SaleID
LIMIT 100;
Sin embargo, el ahorro efectivo depende del plan de ejecución, los índices, el particionado, el almacenamiento y las capacidades del motor. Algunos CDW también pueden aplicar optimizaciones específicas para consultas que combinan ORDER BY y LIMIT, pero no debe asumirse que se aplicarán en todos los casos.
Por otra parte, no utilices LIMIT como única protección en producción. Antes de ejecutar una consulta potencialmente costosa:
- Revisa el plan mediante
EXPLAINo la herramienta equivalente del motor. - Prueba la lógica sobre un intervalo o segmento reducido.
- Utiliza, cuando sea posible, un entorno de desarrollo, una réplica o un warehouse separado.
- Establece límites de tiempo y recursos.
- Comprueba el volumen leído, las filas procesadas y el coste estimado.
- Amplía el alcance de forma progresiva.
La sintaxis para limitar resultados varía según el motor. PostgreSQL, Snowflake, Redshift y MySQL admiten LIMIT; otros sistemas utilizan construcciones como FETCH FIRST, OFFSET ... FETCH o TOP.
En una consulta con GROUP BY y ORDER BY, LIMIT suele aplicarse después de filtrar, agregar y ordenar los resultados. Por ello, puede reducir las filas transferidas y mostradas, pero no necesariamente el volumen de datos leído o procesado. Utiliza EXPLAIN —o la herramienta equivalente del motor— para comprobar el plan real.
(8) - Programa las cargas intensivas fuera de las horas punta
Cuando una consulta o un proceso es intensivo por naturaleza y no necesita ejecutarse de forma interactiva, conviene programarlo en una ventana de baja concurrencia. Esto reduce la competencia por CPU, memoria, conexiones y capacidad de procesamiento con las aplicaciones, usuarios y procesos críticos del negocio. Esta medida no sustituye la optimización. Una consulta ineficiente seguirá consumiendo recursos aunque se ejecute de madrugada. La ventana de ejecución debe considerarse una medida adicional de control operativo, no una solución para consultas mal diseñadas.
Evalúa el coste real antes de programar
No existe un umbral universal de filas o una construcción SQL que determine por sí sola que una consulta deba ejecutarse fuera de las horas punta. La decisión debe basarse en indicadores como:
- Duración estimada y observada.
- Filas o bytes leídos y procesados.
- Memoria y capacidad de cómputo necesarias.
- Número y cardinalidad de los
JOIN. - Operaciones de ordenación, agregación o deduplicación.
- Concurrencia prevista.
- Posibles bloqueos o contención sobre las tablas.
- Coste estimado en el Cloud Data Warehouse.
- Impacto sobre los SLA de las aplicaciones y dashboards.
Revisa estos indicadores mediante EXPLAIN, el historial de consultas o las herramientas de observabilidad del motor.
EVITAR
Lo que debes evitar es trasladar una consulta incorrecta a otra franja horaria. Una condición de unión ausente, un producto cartesiano accidental o una dependencia circular deben corregirse antes de ejecutar el proceso. Programarlos durante la noche puede reducir temporalmente su impacto sobre los usuarios, pero no elimina el riesgo de saturación, fallo o consumo descontrolado.
Del mismo modo, elementos como DISTINCT, las subconsultas o la consulta de varios esquemas no son necesariamente ineficientes. Su coste depende de cómo los procese el motor y del volumen de datos implicado.
BUENA PRÁCTICA
Lo adecuado es separar las cargas batch de las interactivas. Los procesos de extracción, transformación, consolidación o reconstrucción completa suelen ser mejores candidatos para una ejecución programada. Siempre que los requisitos de actualización lo permitan, deben situarse en una ventana con menor actividad y coordinarse con otros procesos de la plataforma.
La ventana adecuada no tiene que ser necesariamente de madrugada. En organizaciones internacionales o con actividad continua, debe definirse a partir de los patrones reales de uso, las zonas horarias, los cierres operativos y las demás cargas programadas.
Impacto en Sisense
Sisense permite programar los builds de ElastiCube por días y horas o mediante intervalos. Cuando un build extrae grandes volúmenes, recalcula transformaciones o compite con procesos críticos de las fuentes, conviene situarlo en una ventana de menor actividad. La programación debe coordinarse tanto con el uso de Sisense como con la capacidad de los sistemas de origen. Aunque los dashboards consulten el ElastiCube y no directamente esas fuentes, el proceso de build sí necesita acceder a ellas para actualizar el modelo.
En Live, las consultas se ejecutan directamente contra la fuente cuando los dashboards necesitan actualizar sus resultados. Por tanto, las interacciones de los usuarios no pueden trasladarse simplemente a una ventana nocturna. Sisense advierte de que la fuente debe soportar la frecuencia de refresco y la carga generada por las consultas Live. En este escenario, el control debe realizarse mediante otras medidas:
- Optimización del modelo y de las consultas.
- Reducción de la frecuencia de actualización cuando sea posible.
- Caché y reutilización de resultados.
- Límites de tiempo, filas y recursos.
- Separación de cargas mediante warehouses o recursos dedicados.
- Materialización previa de cálculos reutilizables.
- Monitorización de concurrencia, latencia y coste.
Sisense permite configurar, entre otros parámetros, límites de resultados y frecuencias de actualización para los modelos Live.
En B2D deben diferenciarse dos cargas:
- El build, que crea o actualiza las tablas del modelo en el CDW y puede programarse en una ventana adecuada.
- Las consultas de los dashboards, que posteriormente se ejecutan contra esas tablas con un comportamiento equivalente a Live.
Programar correctamente el build ayuda a controlar la competencia por recursos en el CDW, pero no optimiza las consultas interactivas que se producirán después.
(9) - Valida el modelo antes de publicarlo
Una consulta puede ser sintácticamente correcta y, aun así, producir métricas incorrectas, multiplicar registros o generar una carga excesiva cuando se integra en un modelo de Sisense. Antes de publicar cambios, valida no solo el SQL, sino también el comportamiento del modelo: relaciones, cardinalidad, granularidad, transformaciones, cálculos, filtros y reglas de seguridad.
EVITAR
Debes evitar validar únicamente con unas pocas filas. Una muestra demasiado pequeña o arbitraria puede confirmar que una expresión funciona, pero no necesariamente que el modelo sea correcto. Puede no incluir:
- Relaciones uno a muchos o muchos a muchos.
- Claves duplicadas o valores nulos.
- Registros sin correspondencia entre tablas.
- Fechas, importes o categorías excepcionales.
- Combinaciones de filtros que generan resultados incorrectos.
- Distribuciones de datos que afectan al rendimiento.
Utiliza una muestra controlada y representativa, que incluya tanto los casos habituales como los casos límite. Después, amplía progresivamente el volumen para comprobar cómo escala el modelo.
BUENA PRÁCTICA
Lo adecuado es validar por capas. Antes de llevar un modelo a producción, comprueba al menos cuatro dimensiones.
- Exactitud funcional. Confirma que las métricas, dimensiones y filtros responden al requisito de negocio y se reconcilian con una fuente de referencia.
- Integridad del modelo. Revisa las claves, la cardinalidad, las rutas entre tablas y la granularidad esperada. Comprueba especialmente que los
JOINy las relaciones visuales no multipliquen registros ni provoquen agregaciones inconsistentes. - Rendimiento. Mide la duración, el volumen procesado y el consumo de recursos con datos representativos. Una transformación que funciona correctamente sobre mil filas puede comportarse de forma muy diferente cuando se aplica a cientos de millones.
- Seguridad. Valida que las reglas de acceso, la segmentación de datos y los filtros de usuario producen el resultado esperado para cada perfil antes de compartir el modelo o el dashboard.
Impacto en Sisense
En un modelo ElastiCube, antes de ejecutar un build completo, utiliza las opciones de edición y previsualización para comprobar las consultas de importación, las tablas personalizadas y los campos calculados. Cuando sea posible, comienza con un subconjunto representativo de los datos. Después, ejecuta un build con un volumen suficiente para validar la cardinalidad, las transformaciones y el rendimiento real del modelo.
Esta validación progresiva ayuda a detectar problemas antes de invertir horas en una construcción completa o de incorporar al ElastiCube estructuras incorrectas que afecten posteriormente a todos los dashboards.
En un modelo Live, las consultas personalizadas, los filtros y los cálculos se procesan contra la fuente. Por ello, la validación no debe limitarse a comprobar que la consulta devuelve datos. Antes de publicar el modelo:
- Revisa la consulta generada y su plan de ejecución.
- Comprueba el volumen leído y devuelto.
- Prueba los filtros y recorridos de drill más habituales.
- Valida la concurrencia prevista.
- Verifica el comportamiento con usuarios y reglas de seguridad diferentes.
- Publica inicialmente en un entorno controlado o para un grupo limitado de usuarios.
Una consulta ineficiente o una relación incorrecta puede repetirse cada vez que los usuarios interactúan con los dashboards.
En B2D deben validarse por separado el proceso de construcción y el comportamiento posterior de las consultas. Durante el build, comprueba la estrategia de carga, la columna de referencia utilizada por Incremental, la clave única definida para Upsert, la estructura de las tablas generadas y el consumo de recursos del CDW. Una vez publicado, valida el modelo como una conexión Live: tiempos de respuesta, consultas generadas, concurrencia y coste de procesamiento sobre el warehouse.
Antes de publicar no consideres validado un modelo únicamente porque el SQL se ejecute sin errores o porque una vista previa muestre resultados plausibles. Confirma que:
- Las métricas coinciden con la fuente de verdad.
- La granularidad es la esperada.
- Las relaciones no multiplican registros.
- Los valores nulos y duplicados se gestionan correctamente.
- Los filtros y drills mantienen la coherencia.
- Las reglas de seguridad funcionan para todos los perfiles.
- El rendimiento es aceptable con un volumen y una concurrencia representativos.
- Existe un procedimiento para revertir el cambio si aparece un problema.
La validación con muestras permite detectar errores pronto; la validación con volumen representativo determina si el modelo está realmente preparado para producción.
SQL correcto no es SQL listo para producción
Una consulta no está preparada para producción únicamente porque devuelva el resultado esperado. También debe procesar el volumen adecuado, respetar la granularidad del modelo, utilizar correctamente las relaciones y mantener un comportamiento estable cuando aumenten los datos, la concurrencia y la frecuencia de ejecución.
Las nueve prácticas expuestas en este post permiten reducir gran parte de los riesgos más habituales: partir de un requisito claro, seleccionar únicamente la información necesaria, comprender el origen de las duplicidades, declarar correctamente los JOIN, aplicar los filtros en la fase adecuada, optimizar las búsquedas de texto, controlar el volumen procesado, separar las cargas intensivas de las interactivas y validar el modelo antes de publicarlo.
Ninguna de ellas sustituye el criterio técnico, pero juntas reducen la distancia entre una consulta que “funciona” y una consulta en la que tu entorno productivo puede confiar.
¿Tienes dudas sobre si tus consultas están realmente preparadas para producción?
Hablemos y revisemos conjuntamente el volumen de datos, el modelo de despliegue y los patrones de consulta para evitar que tu entorno productivo pague el coste de un SQL mal diseñado.
Descubre cómo aplicar estas prácticas viendo Sisense en acción.
Parapentex Studios, July 2026
