Saltar al contenido principal
PREWHERE es una optimización para aplicar el filtrado de forma más eficiente. Está habilitada de forma predeterminada aunque la cláusula PREWHERE no se especifique explícitamente. Funciona moviendo automáticamente parte de la condición WHERE a la etapa de prewhere. La función de la cláusula PREWHERE es únicamente controlar esta optimización si cree que sabe hacerlo mejor que como ocurre de forma predeterminada. Con la optimización de prewhere, primero solo se leen las columnas necesarias para ejecutar la expresión de prewhere. Después, se leen las demás columnas necesarias para ejecutar el resto de la consulta, pero solo en aquellos bloques en los que la expresión de prewhere es true al menos para algunas filas. Si hay muchos bloques en los que la expresión de prewhere es false para todas las filas y prewhere necesita menos columnas que otras partes de la consulta, esto a menudo permite leer muchos menos datos del disco para ejecutar la consulta.

Control de PREWHERE manualmente

La cláusula tiene el mismo significado que la cláusula WHERE. La diferencia está en qué datos se leen de la tabla. Cuando se controla manualmente PREWHERE para condiciones de filtrado que se usan en una minoría de las columnas de la consulta, pero que ofrecen un filtrado de datos eficaz, se reduce el volumen de datos que se debe leer. Una consulta puede especificar PREWHERE y WHERE simultáneamente. En este caso, PREWHERE precede a WHERE. Si la configuración optimize_move_to_prewhere está establecida en 0, se desactivan las heurísticas que mueven automáticamente partes de las expresiones de WHERE a PREWHERE. Si la consulta tiene el modificador FINAL, la optimización de PREWHERE no siempre es correcta. Solo se habilita si ambas configuraciones optimize_move_to_prewhere y optimize_move_to_prewhere_if_final están activadas.
La sección PREWHERE se ejecuta antes de FINAL, por lo que los resultados de las consultas FROM ... FINAL pueden verse sesgados al usar PREWHERE con campos que no están en la sección ORDER BY de una tabla.

Limitaciones

PREWHERE solo se admite en tablas de la familia *MergeTree.

Ejemplo

CREATE TABLE mydata
(
    `A` Int64,
    `B` Int8,
    `C` String
)
ENGINE = MergeTree
ORDER BY A AS
SELECT
    number,
    0,
    if(number between 1000 and 2000, 'x', toString(number))
FROM numbers(10000000);

SELECT count()
FROM mydata
WHERE (B = 0) AND (C = 'x');

1 row in set. Elapsed: 0.074 sec. Processed 10.00 million rows, 168.89 MB (134.98 million rows/s., 2.28 GB/s.)

-- habilitemos el tracing para ver qué predicados se mueven a PREWHERE
set send_logs_level='debug';

MergeTreeWhereOptimizer: condition "B = 0" moved to PREWHERE  
-- ClickHouse mueve automáticamente `B = 0` a PREWHERE, pero no tiene sentido porque B siempre es 0.

-- Movamos el otro predicado `C = 'x'` 

SELECT count()
FROM mydata
PREWHERE C = 'x'
WHERE B = 0;

1 row in set. Elapsed: 0.069 sec. Processed 10.00 million rows, 158.89 MB (144.90 million rows/s., 2.30 GB/s.)

-- Esta consulta con `PREWHERE` manual procesa ligeramente menos datos: 158.89 MB VS 168.89 MB
Última modificación el 10 de junio de 2026