Restricción de partición no utilizada para uniones que involucran tablas particionadas por marca de tiempo


11

Tengo una estructura de tabla particionada como:

CREATE TABLE measurements (
    sensor_id bigint,
    tx timestamp,
    measurement int
);

CREATE TABLE measurements_201201(
    CHECK (tx >= '2012-01-01 00:00:00'::timestamp without time zone 
       AND tx < ('2012-01-01 00:00:00'::timestamp without time zone + '1 mon'::interval))    
)INHERITS (measurements);
CREATE INDEX ON measurements_201201(sensor_id);
CREATE INDEX ON measurements_201201(tx);
CREATE INDEX ON measurements_201201(sensor_id, tx);
....

Y así. Cada tabla tiene aproximadamente 20 millones de filas.

Si busco una muestra de sensores y una muestra de marcas de tiempo en la WHEREcláusula, el plan de consulta muestra las tablas correctas que se seleccionan y los índices que se utilizan, por ejemplo:

SELECT *
FROM measurements
INNER JOIN sensors TABLESAMPLE BERNOULLI (0.01) USING (sensor_id)
WHERE tx BETWEEN '2015-01-04 05:00' AND '2015-01-04 06:00' 
    OR tx BETWEEN '2015-02-04 05:00' AND '2015-02-04 06:00' 
    OR tx BETWEEN '2014-03-05 05:00' AND '2014-04-07 06:00' ;

Sin embargo, si uso un CTE, o pongo los valores de la marca de tiempo en una tabla (no se muestra, incluso con índices en la tabla temporal).

WITH sensor_sample AS(
    SELECT sensor_id, start_ts, end_ts
    FROM sensors TABLESAMPLE BERNOULLI (0.01)
    CROSS JOIN (VALUES (TIMESTAMP '2015-01-04 05:00', TIMESTAMP '2015-01-04 06:00'),
        (TIMESTAMP '2015-02-04 05:00', TIMESTAMP '2015-02-04 06:00'),
        (TIMESTAMP  '2014-03-05 05:00', '2014-04-07 06:00') ) tstamps(start_ts, end_ts)
)

Algo como lo de abajo

SET constraint_exclusion = on;
SELECT * FROM measurements
INNER JOIN sensor_sample USING (sensor_id)
WHERE tx BETWEEN start_ts AND end_ts

Realiza una exploración de índice en cada tabla. Lo que aún es relativamente rápido, pero con una complejidad cada vez mayor de consultas, esto puede convertirse en escaneos seq que terminarán siendo muy lentos para recuperar ~ 40K filas de un subconjunto limitado de tablas particionadas (4-5 de 50).

Me preocupa que algo como esto sea ​​el problema.

Para expresiones no triviales, debe repetir la condición más o menos textualmente en las consultas para que el planificador de consultas de Postgres comprenda que puede confiar en la restricción CHECK. ¡Incluso si parece redundante!

¿Cómo puedo mejorar la estructura de particionamiento y consulta para reducir la probabilidad de ejecutar exploraciones seq en todos mis datos?


1
gran pregunta, pero sería aún mejor si pega los resultados de EXPLAIN (ANALYZE, BUFFERS)
filiprem

Respuestas:


1

La exclusión basada en restricciones [CBE] se realiza en la etapa inicial de la planificación de la consulta, justo después de analizar la consulta, asignarla a las relaciones reales y reescribirla. ( internos , etapa de planificador / optimizador)

El planificador no puede asumir ningún contenido de la tabla "sensor_sample".

Por lo tanto, a menos que tenga valores codificados en la consulta, el planificador no excluirá "particiones".

Supongo que sucede con la variante CTE ... el planificador está restringido porque usas TABLESAMPLE y toda la subconsulta puede tratarse como volátil incluso si los literales en la subconsulta son estáticos. ( eso es solo mi suposición, no soy experto en código de planificador )

En el lado positivo, la exploración de índice con resultado negativo es increíblemente rápida. (¡escaneo de una sola página como máximo!) así que a menos que tenga más de 10000 particiones, no me molestaría.

Entonces, para responder su pregunta directamente:

  • No puede mejorar esta estructura de datos mucho más.

  • En cuanto a los escaneos de índice, son baratos;

  • Con respecto a los escaneos secuenciales: se evitan cuando sea posible, como puede ver en sus propios ejemplos.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.