为啥这个查询这么慢? - PostgreSQL - 从 SERIAL、TIMESTAMP 和 NUMERIC(6,2) 中选择

Posted

技术标签:

【中文标题】为啥这个查询这么慢? - PostgreSQL - 从 SERIAL、TIMESTAMP 和 NUMERIC(6,2) 中选择【英文标题】:Why this query is so slow? - PostgreSQL - selecting from SERIAL, TIMESTAMP and NUMERIC(6,2)为什么这个查询这么慢? - PostgreSQL - 从 SERIAL、TIMESTAMP 和 NUMERIC(6,2) 中选择 【发布时间】:2016-10-10 20:54:28 【问题描述】:

这是我的measurement_pm2_5 表:

CREATE TABLE public.measurement_pm2_5 (
  sensor_id SERIAL,
  measurement_time TIMESTAMP WITHOUT TIME ZONE NOT NULL,
  measurement_value NUMERIC(6,2) NOT NULL,
  CONSTRAINT measurement_pm2_5_sensor_id_fkey FOREIGN KEY (sensor_id)
    REFERENCES public.sensor(id)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION
    NOT DEFERRABLE
) 
WITH (oids = false);

这是我的查询:

select sensor_id, measurement_time, measurement_value 
FROM "public"."measurement_pm10" p, 
      (values(64,1476094463,1476116063),(129,1476094463,1476116063),(66,1476094463,1476116063),(130,1476094463,1476116063),(3,1476094463,1476116063),(131,1476094463,1476116063),(132,1476094463,1476116063),(133,1476094463,1476116063),(134,1476094463,1476116063),(135,1476094463,1476116063),(136,1476094463,1476116063),(137,1476094463,1476116063),(138,1476094463,1476116063),(139,1476094463,1476116063),(142,1476094463,1476116063),(17,1476094463,1476116063),(18,1476094463,1476116063),(19,1476094463,1476116063),(148,1476094463,1476116063),(94,1476094463,1476116063),(96,1476094463,1476116063),(101,1476094463,1476116063),(58,1476094463,1476116063),(59,1476094463,1476116063),(60,1476094463,1476116063),(63,1476094463,1476116063)) as t(sensor,t1,t2)
WHERE p.sensor_id = t.sensor 
  AND measurement_time BETWEEN to_timestamp(t.t1) AND to_timestamp(t.t2);

数据库执行并给出响应大约需要 16 秒。 它返回大约 3k 行。一般这个表有260k行。

有什么方法可以加快速度吗?更快是指在不到一秒的时间内执行它?

我使用 AWS 的免费套餐的 PostgreSQL 数据库。

EXPLAIN (ANALYZE, BUFFER):

Hash Join  (cost=0.65..8056.77 rows=5835 width=18) (actual time=15308.237..16039.319 rows=3035 loops=1)
  Hash Cond: (p.sensor_id = "*VALUES*".column1)
  Join Filter: ((p.measurement_time >= to_timestamp(("*VALUES*".column2)::double precision)) AND (p.measurement_time <= to_timestamp(("*VALUES*".column3)::double precision)))
  Rows Removed by Join Filter: 182836
  Buffers: shared hit=2330
  ->  Seq Scan on measurement_pm10 p  (cost=0.00..5538.74 rows=321174 width=18) (actual time=0.007..1657.386 rows=321229 loops=1)
        Buffers: shared hit=2327
  ->  Hash  (cost=0.33..0.33 rows=26 width=12) (actual time=0.018..0.018 rows=26 loops=1)
        Buckets: 1024  Batches: 1  Memory Usage: 10kB
        ->  Values Scan on "*VALUES*"  (cost=0.00..0.33 rows=26 width=12) (actual time=0.002..0.010 rows=26 loops=1)
Planning time: 0.560 ms
Execution time: 16040.164 ms

【问题讨论】:

可能相关:***.com/a/39246869/251311 但如果您提供EXPLAIN ANALYZE 那就太好了。 PS:你的表中真的没有索引吗? @zerkms 感谢您提供链接问题。您能帮我构建加入 CTE 的查询吗?我不确定我应该把我的条件放在哪里。我用EXPLAIN (ANALYZE, BUFFER)更新了我的帖子。 好吧,您至少需要为sensor_id 列添加一个索引(因为它无论如何都是FK),然后显示它的更新计划。 我会尝试在(sensor_id, measurement_time)上建立索引 我在(sensor_id, measurement_time) 上添加了索引,现在它在大约 300 毫秒内执行!非常感谢! 【参考方案1】:

当您根据时间戳过滤值时,在时间戳上创建一个非聚集索引。这肯定会有所帮助

【讨论】:

所有索引在 Postgres 中都是“非聚集的”

以上是关于为啥这个查询这么慢? - PostgreSQL - 从 SERIAL、TIMESTAMP 和 NUMERIC(6,2) 中选择的主要内容,如果未能解决你的问题,请参考以下文章

为啥 QuerySet 迭代这么慢?

为啥这个查询运行这么慢?

为啥这个 pg 查询这么慢?我怎样才能让它更快?

为啥这个 jQuery 选择器这么慢?

为啥这个交叉连接在 Linq 中这么慢?

为啥我在postgresql的json数据中查询,速度会比mysql慢很多