Postgres的查询:异常磁盘I / O

问题描述 投票:1回答:1

我生产的查询遭受奇怪的I / O命中的,我想不出问题出在哪里。我的意思是,这是没有任何大规模的加入或类似的东西一个简单的查询...

我的表有围绕行的300K,并且变得像每天15 / 20K行,这里是表的定义:

CREATE TABLE public.tv_smartdevicemeasurement_modbus
(
    measurement_id integer NOT NULL DEFAULT nextval('tv_smartdevicemeasurement_modbus_measurement_id_seq'::regclass),
    insert_time timestamp with time zone NOT NULL,
    data jsonb NOT NULL,
    parent_job_id integer NOT NULL,
    smart_device_id integer NOT NULL,
    CONSTRAINT tv_smartdevicemeasurement_modbus_pkey PRIMARY KEY (measurement_id),
    CONSTRAINT tv_smartdevicemeasur_parent_job_id_1ac4609e_fk_tv_measur FOREIGN KEY (parent_job_id)
        REFERENCES public.tv_measurementjobs (job_id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION
        DEFERRABLE INITIALLY DEFERRED,
    CONSTRAINT tv_smartdevicemeasur_smart_device_id_62c12ed0_fk_tv_smartd FOREIGN KEY (smart_device_id)
        REFERENCES public.tv_smartdevice_modbus (device_id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION
        DEFERRABLE INITIALLY DEFERRED
)
WITH (
    OIDS = FALSE
)
TABLESPACE pg_default;

CREATE INDEX tv_smartdevicemeasurement_modbus_parent_job_id_1ac4609e
    ON public.tv_smartdevicemeasurement_modbus USING btree
    (parent_job_id)
    TABLESPACE pg_default;

CREATE INDEX tv_smartdevicemeasurement_modbus_smart_device_id_62c12ed0
    ON public.tv_smartdevicemeasurement_modbus USING btree
    (smart_device_id)
    TABLESPACE pg_default;

下面是该查询:

EXPLAIN (ANALYZE, BUFFERS)
SELECT "tv_smartdevicemeasurement_modbus"."measurement_id",
       "tv_smartdevicemeasurement_modbus"."smart_device_id",
       "tv_smartdevicemeasurement_modbus"."parent_job_id",
       "tv_smartdevicemeasurement_modbus"."insert_time",
       "tv_smartdevicemeasurement_modbus"."data",
  (SELECT DATA->> 'VLN_AVG') AS "VLN_AVG",
  (SELECT DATA->> 'VLN3') AS "VLN3",
  (SELECT DATA->> 'VLN2') AS "VLN2",
  (SELECT DATA->> 'VLN1') AS "VLN1",
  (SELECT DATA->> 'VL1-2') AS "VL1-2",
  (SELECT DATA->> 'VL2-3') AS "VL2-3",
  (SELECT DATA->> 'VL3-1') AS "VL3-1",
  (SELECT DATA->> 'VLL_AVG') AS "VLL_AVG",
  (SELECT DATA->> 'IL_AVG') AS "IL_AVG",
  (SELECT DATA->> 'IL1') AS "IL1",
  (SELECT DATA->> 'IL2') AS "IL2",
  (SELECT DATA->> 'IL3') AS "IL3",
  (SELECT DATA->> 'PL_SUM') AS "PL_SUM",
  (SELECT DATA->> 'PL2') AS "PL2",
  (SELECT DATA->> 'PL3') AS "PL3",
  (SELECT DATA->> 'PL1') AS "PL1",
  (SELECT DATA->> 'kWh_L2') AS "kWh_L2",
  (SELECT DATA->> 'kWh_L3') AS "kWh_L3",
  (SELECT DATA->> 'kWh_L1') AS "kWh_L1",
  (SELECT DATA->> 'QL3') AS "QL3",
  (SELECT DATA->> 'QL1') AS "QL1",
  (SELECT DATA->> 'QL2') AS "QL2",
  (SELECT DATA->> 'QL_SUM') AS "QL_SUM",
  (SELECT DATA->> 'SL1') AS "SL1",
  (SELECT DATA->> 'SL2') AS "SL2",
  (SELECT DATA->> 'SL3') AS "SL3",
  (SELECT DATA->> 'SL_SUM') AS "SL_SUM",
  (SELECT DATA->> 'KVARh_L1') AS "KVARh_L1",
  (SELECT DATA->> 'KVARh_L2') AS "KVARh_L2",
  (SELECT DATA->> 'KVARh_LSUM') AS "KVARh_LSUM",
  (SELECT DATA->> 'KVARh_L3') AS "KVARh_L3",
  (SELECT DATA->> 'KVAh_L3') AS "KVAh_L3",
  (SELECT DATA->> 'KVAh_L1') AS "KVAh_L1",
  (SELECT DATA->> 'KVAh_L2') AS "KVAh_L2",
  (SELECT DATA->> 'KVAh_LSUM') AS "KVAh_LSUM",
  (SELECT DATA->> 'Cos_LSUM') AS "Cos_LSUM",
  (SELECT DATA->> 'Cos_L1') AS "Cos_L1",
  (SELECT DATA->> 'Cos_L2') AS "Cos_L2",
  (SELECT DATA->> 'Cos_L3') AS "Cos_L3"
FROM "tv_smartdevicemeasurement_modbus"
WHERE ("tv_smartdevicemeasurement_modbus"."insert_time" > '2019-02-07 12:15:00+01:00'
       AND "tv_smartdevicemeasurement_modbus"."insert_time" < '2019-02-07 12:31:00+01:00'
       AND "tv_smartdevicemeasurement_modbus"."smart_device_id" = 6)

并且存在与执行计划解释分析缓冲液:https://explain.depesz.com/s/d3f

非常,非常奇怪!

postgresql database-performance
1个回答
2
投票

这是不奇怪或不正常的。

既然你没有对insert_time索引和PostgreSQL只能用在smart_device_id索引,以加快查询。

但是,条件是不是非常有选择性的,它有30270个结果行,其每一个具有它们是否满足上insert_time附加过滤条件进行检查。该过滤器将删除这些行的30258,只留下12落后。

获取从表中的这些行30270,PostgreSQL的不得不从磁盘,这是你的时间都花在阅读每8 KB的21442块。

最好的指标是:

CREATE INDEX ON tv_smartdevicemeasurement_modbus (smart_device_id, insert_time);

但我怀疑,下面的指标,这是更广泛的应用和更小,也将提供良好的响应时间:

CREATE INDEX ON tv_smartdevicemeasurement_modbus (insert_time);
© www.soinside.com 2019 - 2024. All rights reserved.