我遇到了一个需要几十分钟的查询问题。
SELECT MAX(ts)
FROM sensor_values
WHERE ts >= '2020-09-01'
AND ts <= '2023-02-01'
AND sensor_id = 3502;
此sensor_id
没有数据,因此应返回0行。
我的sensor_values
表是一个基于季度的分区表。
定义是
CREATE TABLE IF NOT EXISTS public.sensor_values
(
ts timestamp with time zone NOT NULL,
value double precision NOT NULL DEFAULT 'NaN'::double precision,
sensor_id integer NOT NULL,
status tridium_status NOT NULL DEFAULT 'unknown'::tridium_status,
CONSTRAINT sensor_values_ts_sensor_unq UNIQUE (ts, sensor_id),
CONSTRAINT sensor_values_sensor_id_fkey FOREIGN KEY (sensor_id)
REFERENCES public.sensors (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
)
子表示例
CREATE TABLE IF NOT EXISTS public.sensor_values_2020q1
(
CONSTRAINT sensor_values_2020q1_ts_sensor_unq UNIQUE (ts, sensor_id),
CONSTRAINT sensor_values_2020q1_ts_check CHECK (ts >= '2020-01-01 00:00:00+00'::timestamp with time zone AND ts < '2020-04-01 00:00:00+00'::timestamp with time zone)
)
INHERITS (public.sensor_values)
TABLESPACE pg_default;
unique约束似乎是在表上添加索引
下面是一个解释分析的例子
EXPLAIN ANALYZE SELECT MAX(ts)FROM sensor_values WHERE ts >= '2022-05-01' AND ts <= '2023-02-01' AND sensor_id = 3502;
QUERY PLAN
Result (cost=62.73..62.74 rows=1 width=8) (actual time=993680.100..993680.106 rows=1 loops=1)
InitPlan 1 (returns $0)
-> Limit (cost=2.44..62.73 rows=1 width=8) (actual time=993680.097..993680.101 rows=0 loops=1)
-> Merge Append (cost=2.44..4665674.90 rows=77386 width=8) (actual time=993680.095..993680.099 rows=0 loops=1)
Sort Key: sensor_values.ts DESC
-> Index Only Scan Backward using sensor_values_ts_sensor_unq on sensor_values sensor_values_1 (cost=0.12..8.15 rows=1 width=8) (actual time=0.007..0.008 rows=0 loops=1)
Index Cond: ((ts IS NOT NULL) AND (ts >= '2022-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone) AND (sensor_id = 3502))
Heap Fetches: 0
-> Index Only Scan Backward using sensor_values_2022q2_ts_sensor_unq on sensor_values_2022q2 sensor_values_2 (cost=0.56..940388.51 rows=15212 width=8) (actual time=446572.203..446572.203 rows=0 loops=1)
Index Cond: ((ts IS NOT NULL) AND (ts >= '2022-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone) AND (sensor_id = 3502))
Heap Fetches: 0
-> Index Only Scan Backward using sensor_values_2022q3_ts_sensor_unq on sensor_values_2022q3 sensor_values_3 (cost=0.56..1943951.19 rows=31973 width=8) (actual time=544350.923..544350.923 rows=0 loops=1)
Index Cond: ((ts IS NOT NULL) AND (ts >= '2022-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone) AND (sensor_id = 3502))
Heap Fetches: 0
-> Index Only Scan Backward using sensor_values_2022q4_ts_sensor_unq on sensor_values_2022q4 sensor_values_4 (cost=0.56..1300948.18 rows=22290 width=8) (actual time=2160.317..2160.317 rows=0 loops=1)
Index Cond: ((ts IS NOT NULL) AND (ts >= '2022-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone) AND (sensor_id = 3502))
Heap Fetches: 0
-> Index Only Scan Backward using sensor_values_2023q1_ts_sensor_unq on sensor_values_2023q1 sensor_values_5 (cost=0.56..479093.44 rows=7910 width=8) (actual time=596.637..596.637 rows=0 loops=1)
Index Cond: ((ts IS NOT NULL) AND (ts >= '2022-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone) AND (sensor_id = 3502))
Heap Fetches: 0
Planning Time: 4.134 ms
Execution Time: 993680.161 ms
你可以看到16分钟。它似乎做索引扫描
WA在top是在50%运行这个。
如果我重新启动postgres并通过从上面花了一段时间的子表中选择重新检查,它是即时的
例如
SELECT MAX(ts)
FROM sensor_values_2022q2
WHERE ts >= '2022-05-01'
AND ts <= '2023-02-01'
AND sensor_id = 3502;
只需要几秒钟。
我已对所有表和VACUUM运行分析
这是Postgres 15,我已经设置了6 GB的共享内存和effective_cache内存。
我还可以在这里检查什么?
谢谢你的任何建议。
在弗兰克斯的建议之后。事情进展很快
SELECT MAX(ts)FROM sensor_values WHERE ts >= '2000-05-01' AND ts <= '2023-02-01' AND sensor_id = 3502;
现在在几分之一秒内完成。
EXPLAIN(ANALYZE,BUFFERS)SELECT MAX(ts)FROM sensor_values WHERE ts >= '2000-05-01' AND ts <= '2023-02-01' AND sensor_id = 3502;
示出
QUERY PLAN
Result (cost=13.16..13.17 rows=1 width=8) (actual time=0.475..0.479 rows=1 loops=1)
Buffers: shared hit=94
InitPlan 1 (returns $0)
-> Limit (cost=13.09..13.16 rows=1 width=8) (actual time=0.472..0.475 rows=0 loops=1)
Buffers: shared hit=94
-> Merge Append (cost=13.09..41718.45 rows=603739 width=8) (actual time=0.470..0.473 rows=0 loops=1)
Sort Key: sensor_values.ts DESC
Buffers: shared hit=94
-> Index Only Scan Backward using sensor_values_ts_sensor_unq on sensor_values sensor_values_1 (cost=0.12..8.15 rows=1 width=8) (actual time=0.026..0.026 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=2
-> Index Only Scan Backward using sensor_values_2017q1_ts_sensor_unq on sensor_values_2017q1 sensor_values_2 (cost=0.12..8.15 rows=1 width=8) (actual time=0.014..0.014 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=2
-> Index Only Scan Backward using sensor_values_2017q2_ts_sensor_unq on sensor_values_2017q2 sensor_values_3 (cost=0.12..8.15 rows=1 width=8) (actual time=0.009..0.009 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=2
-> Index Only Scan Backward using sensor_values_2017q3_ts_sensor_unq on sensor_values_2017q3 sensor_values_4 (cost=0.12..8.15 rows=1 width=8) (actual time=0.026..0.026 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=2
-> Index Only Scan Backward using sensor_values_2017q4_ts_sensor_unq on sensor_values_2017q4 sensor_values_5 (cost=0.12..8.15 rows=1 width=8) (actual time=0.014..0.014 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=2
-> Index Only Scan Backward using sensor_values_2018q1_ts_sensor_unq on sensor_values_2018q1 sensor_values_6 (cost=0.56..1034.86 rows=25532 width=8) (actual time=0.019..0.019 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Only Scan Backward using sensor_values_2018q2_ts_sensor_unq on sensor_values_2018q2 sensor_values_7 (cost=0.56..1012.04 rows=24939 width=8) (actual time=0.018..0.018 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Only Scan Backward using sensor_values_2018q3_ts_sensor_unq on sensor_values_2018q3 sensor_values_8 (cost=0.56..1068.14 rows=26383 width=8) (actual time=0.017..0.017 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Only Scan Backward using sensor_values_2018q4_ts_sensor_unq on sensor_values_2018q4 sensor_values_9 (cost=0.56..823.56 rows=20280 width=8) (actual time=0.020..0.020 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Only Scan Backward using sensor_values_2019q1_ts_sensor_unq on sensor_values_2019q1 sensor_values_10 (cost=0.56..959.59 rows=23641 width=8) (actual time=0.016..0.016 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Only Scan Backward using sensor_values_2019q2_ts_sensor_unq on sensor_values_2019q2 sensor_values_11 (cost=0.56..1012.89 rows=24973 width=8) (actual time=0.020..0.020 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Only Scan Backward using sensor_values_2019q3_ts_sensor_unq on sensor_values_2019q3 sensor_values_12 (cost=0.56..1025.59 rows=25321 width=8) (actual time=0.016..0.016 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Only Scan Backward using sensor_values_2019q4_ts_sensor_unq on sensor_values_2019q4 sensor_values_13 (cost=0.56..1057.36 rows=26112 width=8) (actual time=0.018..0.018 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Only Scan Backward using sensor_values_2020q1_ts_sensor_unq on sensor_values_2020q1 sensor_values_14 (cost=0.56..1048.59 rows=25921 width=8) (actual time=0.030..0.030 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Only Scan Backward using sensor_values_2020q2_ts_sensor_unq on sensor_values_2020q2 sensor_values_15 (cost=0.56..1044.04 rows=25739 width=8) (actual time=0.020..0.020 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Only Scan Backward using sensor_values_2020q3_ts_sensor_unq on sensor_values_2020q3 sensor_values_16 (cost=0.56..1616.09 rows=39981 width=8) (actual time=0.015..0.015 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Only Scan Backward using sensor_values_2020q4_ts_sensor_unq on sensor_values_2020q4 sensor_values_17 (cost=0.56..1717.97 rows=42456 width=8) (actual time=0.018..0.018 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Only Scan Backward using sensor_values_2021q1_ts_sensor_unq on sensor_values_2021q1 sensor_values_18 (cost=0.57..1729.19 rows=42745 width=8) (actual time=0.017..0.017 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Only Scan Backward using sensor_values_2021q2_ts_sensor_unq on sensor_values_2021q2 sensor_values_19 (cost=0.57..1621.57 rows=40040 width=8) (actual time=0.015..0.015 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Only Scan Backward using sensor_values_2021q3_ts_sensor_unq on sensor_values_2021q3 sensor_values_20 (cost=0.57..1620.47 rows=39996 width=8) (actual time=0.018..0.019 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Only Scan Backward using sensor_values_2021q4_ts_sensor_unq on sensor_values_2021q4 sensor_values_21 (cost=0.57..1739.69 rows=43005 width=8) (actual time=0.014..0.014 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Only Scan Backward using sensor_values_2022q1_ts_sensor_unq on sensor_values_2022q1 sensor_values_22 (cost=0.56..883.49 rows=21717 width=8) (actual time=0.018..0.018 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Only Scan Backward using sensor_values_2022q2_ts_sensor_unq on sensor_values_2022q2 sensor_values_23 (cost=0.56..934.06 rows=22780 width=8) (actual time=0.020..0.020 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Only Scan Backward using sensor_values_2022q3_ts_sensor_unq on sensor_values_2022q3 sensor_values_24 (cost=0.56..1295.89 rows=31973 width=8) (actual time=0.016..0.016 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Only Scan Backward using sensor_values_2022q4_ts_sensor_unq on sensor_values_2022q4 sensor_values_25 (cost=0.56..901.81 rows=22290 width=8) (actual time=0.016..0.016 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Only Scan Backward using sensor_values_2023q1_ts_sensor_unq on sensor_values_2023q1 sensor_values_26 (cost=0.56..322.31 rows=7910 width=8) (actual time=0.016..0.016 rows=0 loops=1)
Index Cond: ((sensor_id = 3502) AND (ts IS NOT NULL) AND (ts >= '2000-05-01 00:00:00+00'::timestamp with time zone) AND (ts <= '2023-02-01 00:00:00+00'::timestamp with time zone))
Heap Fetches: 0
Buffers: shared hit=4
Planning:
Buffers: shared hit=648
Planning Time: 7.898 ms
Execution Time: 0.767 ms
不知道为什么命令加快了你的注意。
1条答案
按热度按时间hmmo2u0o1#
只需改变唯一约束,首先是sensor_id,然后是时间戳。这使得数据库可以首先执行等式,然后搜索最后一个时间戳。它应该是索引中的一个元组。
请分享新的查询计划,以显示有哪些变化以及如何提高性能。