为啥这个查询这么慢? - 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) 中选择的主要内容,如果未能解决你的问题,请参考以下文章