分区约束不适用于涉及按时间戳进行分区的表的联接


11

我有一个分区表结构,如:

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);
....

等等。每个表大约有2000万行。

如果我在WHERE子句中查询传感器样本和时间戳样本,则查询计划将显示选择的正确表和正在使用的索引,例如:

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' ;

但是,如果我使用CTE,或将时间戳记值放入表中(即使在临时表上具有索引也未显示)。

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)
)

像下面这样

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

对每个表执行索引扫描。这仍然相对较快,但是随着查询的复杂性增加,这可能会变成seq扫描,从有限的分区表子集中检索约40K行(50的4-5)最终会非常慢。

我担心这样的问题。

对于非平凡的表达式,您必须在查询中重复或多或少的逐字条件,以使Postgres查询计划程序了解其可以依赖CHECK约束。即使看起来多余!

如何改善分区和查询结构,以减少对所有数据运行seq扫描的可能性?


1
一个好问题-但是,如果您粘贴EXPLAIN(分析,
缓冲区

Answers:


1

在查询计划的早期阶段,即在查询被解析,映射到实际关系并重写之后,便会执行基于约束的排除[CBE]。(内部,策划/优化阶段)

计划者不能假定“ sensor_sample”表的任何内容。

因此,除非您在查询中使用硬编码的值,否则计划程序不会排除“分区”。

我猜想CTE变量会发生什么...规划器受到限制,因为您使用TABLESAMPLE,即使子查询中的文字是静态的,整个子查询也可能被视为易失性。(这只是我的猜测,我不是计划者代码方面的专家

从好的方面来说,具有负结果的索引扫描速度非常快。(最多单页扫描!)因此,除非您拥有超过10000个分区,否则我不会打扰。

因此,直接回答您的问题:

  • 您不能进一步改善此数据结构。

  • Regardin索引扫描-价格便宜;

  • 关于顺序扫描-如您在自己的示例中看到的,尽可能避免使用它们。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.