Saltar al contenido principal

Documentation Index

Fetch the complete documentation index at: https://help.treble.ai/llms.txt

Use this file to discover all available pages before exploring further.

Optimización de Consultas

El Data Warehouse está construido sobre ClickHouse, una base de datos columnar. Esto significa que las consultas se comportan diferente a una base de datos relacional tradicional. Aquí te explicamos cómo aprovechar la estructura para obtener resultados rápidos.

Principios Clave

1. Siempre filtra por fecha

Todas las tablas de hechos están particionadas por mes (toYYYYMM(created_at)). Filtrar por fecha permite a ClickHouse saltar particiones enteras sin leerlas.
-- Bueno: ClickHouse lee solo 1 partición
SELECT * FROM fact_conversations
WHERE created_at >= '2026-04-01' AND created_at < '2026-05-01'

-- Malo: ClickHouse lee todas las particiones
SELECT * FROM fact_conversations
WHERE agent_name = 'Juan'

2. No necesitas filtrar por company_id

Tu usuario tiene una política de fila que filtra automáticamente por tu empresa. No necesitas agregar WHERE company_id = ... — se aplica de forma transparente.

3. Selecciona solo las columnas que necesitas

ClickHouse es columnar: solo lee las columnas que mencionas en tu SELECT. Menos columnas = menos datos leídos = más rápido.
-- Bueno: lee solo 3 columnas
SELECT conversation_id, created_at, status
FROM fact_conversations
WHERE created_at >= now() - INTERVAL 7 DAY

-- Evita: lee todas las columnas
SELECT *
FROM fact_conversations
WHERE created_at >= now() - INTERVAL 7 DAY

4. Usa LIMIT para explorar

Cuando estés explorando datos, usa LIMIT para evitar traer millones de filas:
SELECT * FROM fact_agent_messages
WHERE created_at >= now() - INTERVAL 1 DAY
ORDER BY created_at DESC
LIMIT 100

Estructura Interna de las Tablas

Cada tabla tiene un orden de clasificación (sort key) que determina cómo se organizan los datos en disco. Las consultas que filtran por las primeras columnas del sort key son mucho más eficientes.

Sort Keys por Tabla

TablaSort KeyFiltra eficientemente por
fact_conversations(company_id, created_at, conversation_id)fecha, conversation_id
fact_agent_messages(company_id, created_at, message_id)fecha, message_id
fact_redirections(company_id, created_at, redirection_id)fecha
fact_agent_status_changes(company_id, agent_id, created_at)agent_id + fecha
fact_agent_daily(company_id, day, agent_id)día, agent_id
fact_sessions(company_id, created_at, session_id)fecha, session_id
fact_deployment_status(company_id, timestamps_eta, deployment_id)fecha
fact_deployment_daily(company_id, day, poll_id)día, poll_id
fact_inbound_messages(company_id, created_at, session_id)fecha
fact_whatsapp_links(company_id, created_at, event_id)fecha
fact_hsm_responses(company_id, response_date, interaction_answer_id)fecha
company_id es siempre la primera columna del sort key. Como tu usuario tiene un filtro automático por empresa, todas tus consultas aprovechan esta optimización sin que tengas que hacer nada.

Índices Secundarios

Algunas tablas tienen índices adicionales que ayudan a filtrar por columnas que no están en el sort key:
TablaÍndiceColumnaTipoÚtil para
fact_agent_messagesidx_conversation_idconversation_idminmaxBuscar mensajes de una conversación específica
fact_agent_messagesidx_sendersenderbloom_filterFiltrar por sender = 'AGENT' o sender = 'USER'
fact_sessionsidx_poll_idpoll_idminmaxFiltrar por campaña
fact_sessionsidx_inbound_outboundinbound_outboundbloom_filterFiltrar por tipo INBOUND/OUTBOUND
fact_deployment_statusidx_poll_idpoll_idminmaxFiltrar por campaña
fact_deployment_statusidx_statusstatusbloom_filterFiltrar por estado de envío
fact_inbound_messagesidx_poll_idpoll_idminmaxFiltrar por campaña
fact_hsm_responsesidx_hsm_idhsm_idminmaxFiltrar por plantilla HSM
fact_hsm_responsesidx_poll_idpoll_idminmaxFiltrar por campaña

Límites del Sistema

Tu usuario tiene los siguientes límites para proteger la estabilidad del sistema:
LímiteValor
Tiempo máximo de ejecución30 segundos
Máximo de filas leídas50 millones
Máximo de bytes leídos5 GB
Máximo de filas en resultado500,000
Máximo de memoria2 GB
Si tu consulta excede alguno de estos límites, será cancelada automáticamente. Para evitarlo:
  • Agrega filtros de fecha más estrechos
  • Selecciona menos columnas
  • Usa LIMIT
  • Pre-agrega con GROUP BY en lugar de traer filas individuales

Patrones Comunes

JOIN entre tablas de hechos

Puedes cruzar tablas usando conversation_id o survey_user_id:
-- Mensajes de una conversación con datos de la conversación
SELECT
    fc.conversation_id,
    fc.agent_name,
    fm.created_at AS mensaje_fecha,
    fm.sender,
    fm.content
FROM client_analytics.fact_conversations fc
INNER JOIN client_analytics.fact_agent_messages fm
    ON fm.conversation_id = fc.conversation_id
WHERE fc.created_at >= now() - INTERVAL 7 DAY
ORDER BY fm.created_at
LIMIT 1000

JOIN con dimensiones

-- Productividad por equipo (team_name viene de la dimensión)
SELECT
    at.team_name,
    sum(ad.chats_handled) AS chats,
    round(avg(ad.avg_first_response_sec), 0) AS respuesta_promedio_seg
FROM client_analytics.fact_agent_daily ad
INNER JOIN client_analytics.dim_agent_tags at ON at.agent_id = ad.agent_id
WHERE ad.day >= today() - 30
GROUP BY at.team_name
ORDER BY chats DESC

Nivel de servicio personalizado

-- Define tu propio umbral de SLA
SELECT
    toDate(created_at) AS dia,
    count() AS conversaciones,
    countIf(first_response_sec <= 60) AS dentro_60s,
    countIf(first_response_sec <= 120) AS dentro_120s,
    countIf(first_response_sec <= 300) AS dentro_5min,
    round(countIf(first_response_sec <= 120) * 100.0 / count(), 1) AS sla_pct
FROM client_analytics.fact_conversations
WHERE created_at >= now() - INTERVAL 30 DAY
  AND first_response_sec IS NOT NULL
GROUP BY dia
ORDER BY dia DESC