【发布时间】:2020-04-15 15:26:09
【问题描述】:
我有一个包含三列 time_stamp、device_id 和 status s.t status 的表格是 json。 time_stamp 和 device_id 列也有 index。我需要获取不为空的 id 1.3.6.1.4.1.34094.1.1.1.1.1 的最新状态值。
您可以使用下面的 MAX 找到以下命令 With 和 Without 的查询执行时间。
使用 MAX 查询:
SELECT DISTINCT MAX(time_stamp) FROM device.status_events WHERE
(device_id = 7) AND
(status->'1.3.6.1.4.1.34094.1.1.1.1.1' != '{}');
不带 MAX 的查询:
SELECT DISTINCT time_stamp FROM device.status_events WHERE
(device_id = 7) AND
(status->'1.3.6.1.4.1.34094.1.1.1.1.1' != '{}');
第一个查询大约需要 3 秒,第二个查询只需 3 毫秒,有两个不同的计划。我认为两个查询应该有相同的查询计划,为什么它在计算 MAX 时不使用 index?如何提高首次查询的运行时间?
PS我使用的是 postgres 9.6(dockerized 版本)。
这也是表定义。
-- Table: device.status_events
-- DROP TABLE device.status_events;
CREATE TABLE device.status_events
(
time_stamp timestamp with time zone NOT NULL,
device_id bigint,
status jsonb,
is_active boolean DEFAULT true,
CONSTRAINT status_events_device_id_fkey FOREIGN KEY (device_id)
REFERENCES device.devices (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE
)
WITH (
OIDS=FALSE
);
ALTER TABLE device.status_events
OWNER TO monitoring;
-- Index: device.status_events__time_stamp
-- DROP INDEX device.status_events__time_stamp;
CREATE INDEX status_events__time_stamp
ON device.status_events
USING btree
(time_stamp);
【问题讨论】:
-
表是否经常被清理和分析? :
select relname, last_vacuum, last_autovacuum, last_analyze, last_autoanalyze from pg_stat_all_tables where relname='device'的输出是什么; -
@pifor 0 行用于您的查询。但是上表的名称是
status_events,对于relname=status_events,输出是2020-04-09 04:09:54.616319+00,对于last_autoanalyze列(其他列为空)。此外,我经常运行上述查询进行测试,结果与 Q 语句相同,第一个计划/运行时差,第二个计划/运行时好。 -
可能是表 status_events 的统计信息不够准确,尤其是对于列 time_stamp。您可以尝试使用
alter table status_events alter column time_stamp set statistics 1000;之类的内容更改统计设置并再次分析该表。 -
@pifor 我运行了您的查询,没有任何改变。
autoanalyze用于2020-04-09,两个查询的行为也不同。 -
您是否运行过 ALTER TABLE 和 ANALYZE ?
标签: sql database postgresql