【问题标题】:Query execution time increased dramatically without type cast在没有类型转换的情况下,查询执行时间显着增加
【发布时间】:2018-12-04 13:37:34
【问题描述】:

此状态下的查询执行时间超过 5 分钟。如果我删除任何 ::DATE 转换(请参阅代码中的注释),执行时间将变为

例如,如果我将gf.created::DATE 更改为gf.created,性能会显着提高。如果我将gtg.created::DATE 更改为gtg.created,也会发生同样的情况。

如果::DATE 转换各自表现出色,为什么会出现巨大差异?

SELECT gtg6.tipo_ganado, COUNT(gtg6.tipo_ganado) animales  
FROM agroapp.ganado g
INNER JOIN (SELECT gf5.ganado_id, gf5.fundo_id  
            FROM agroapp.ganado_fundo gf5  
            INNER JOIN (SELECT MAX(gf3.ganado_fundo_id) ganado_fundo_id  
                        FROM agroapp.ganado_fundo gf3  
                        INNER JOIN (SELECT gf.ganado_id, MAX(gf.created) created  
                                    FROM agroapp.ganado_fundo gf  
                                    WHERE gf.isactive = 'Y'
                                    -- HERE CHANGING gf.created::DATE TO gf.created
                                    AND gf.created::DATE <= '20181030'::DATE
                                    GROUP BY gf.ganado_id) gf2 ON (gf2.ganado_id = gf3.ganado_id AND gf2.created = gf3.created)  
                        WHERE gf3.isactive = 'Y'  
                        GROUP BY gf3.ganado_id) gf4 ON gf4.ganado_fundo_id = gf5.ganado_fundo_id  
            ) gf6 ON gf6.ganado_id = g.ganado_id
INNER JOIN (SELECT gtg5.ganado_id, gtg5.tipo_ganado  
            FROM agroapp.ganado_tipo_ganado gtg5  
            INNER JOIN (SELECT MAX(gtg3.ganado_tipo_ganado_id) ganado_tipo_ganado_id  
                        FROM agroapp.ganado_tipo_ganado gtg3  
                        INNER JOIN (SELECT gtg.ganado_id, MAX(gtg.created) created  
                                    FROM agroapp.ganado_tipo_ganado gtg  
                                    WHERE gtg.isactive = 'Y'
                                    -- OR HERE CHANGING gtg.created::DATE TO gtg.created
                                    AND gtg.created::DATE <= '20181030'::DATE
                                    GROUP BY gtg.ganado_id) gtg2 ON (gtg2.ganado_id = gtg3.ganado_id AND gtg2.created = gtg3.created)  
                        WHERE gtg3.isactive = 'Y'  
                        GROUP BY gtg3.ganado_id) gtg4 ON gtg4.ganado_tipo_ganado_id = gtg5.ganado_tipo_ganado_id  
            ) gtg6 ON gtg6.ganado_id = g.ganado_id  
 WHERE g.organizacion_id = 21
 GROUP BY gtg6.tipo_ganado
 ORDER BY gtg6.tipo_ganado;

表格定义
所有 3 个表都有大约 50000 行:

CREATE TABLE agroapp.ganado_fundo
(
ganado_fundo_id serial NOT NULL,
organizacion_id integer NOT NULL,
isactive character(1) NOT NULL DEFAULT 'Y'::bpchar,
created timestamp without time zone NOT NULL DEFAULT now(),
createdby numeric(10,0) NOT NULL,
updated timestamp without time zone NOT NULL DEFAULT now(),
updatedby numeric(10,0) NOT NULL,
fundo_id integer NOT NULL,
ganado_id integer NOT NULL,
CONSTRAINT ganado_fundo_pk PRIMARY KEY (ganado_fundo_id),
CONSTRAINT ganado_fk FOREIGN KEY (ganado_id)
    REFERENCES agroapp.ganado (ganado_id) MATCH SIMPLE
    ON UPDATE NO ACTION ON DELETE NO ACTION
)

CREATE TABLE agroapp.ganado_tipo_ganado
(
ganado_tipo_ganado_id serial NOT NULL,
organizacion_id integer NOT NULL,
isactive character(1) NOT NULL DEFAULT 'Y'::bpchar,
created timestamp without time zone NOT NULL DEFAULT now(),
createdby numeric(10,0) NOT NULL,
updated timestamp without time zone NOT NULL DEFAULT now(),
updatedby numeric(10,0) NOT NULL,
tipo_ganado character varying(80) NOT NULL,
ganado_id integer NOT NULL,
CONSTRAINT ganado_tipo_ganado_pk PRIMARY KEY (ganado_tipo_ganado_id),
CONSTRAINT ganado_fk FOREIGN KEY (ganado_id)
    REFERENCES agroapp.ganado (ganado_id) MATCH SIMPLE
    ON UPDATE NO ACTION ON DELETE NO ACTION
)

CREATE TABLE agroapp.ganado
(
ganado_id serial NOT NULL,
organizacion_id integer NOT NULL,
isactive character(1) NOT NULL DEFAULT 'Y'::bpchar,
created timestamp without time zone NOT NULL DEFAULT now(),
createdby numeric(10,0) NOT NULL,
updated timestamp without time zone NOT NULL DEFAULT now(),
updatedby numeric(10,0) NOT NULL,
fecha_nacimiento timestamp without time zone NOT NULL,
tipo_ganado character varying(80) NOT NULL,
diio_id integer NOT NULL,
fundo_id integer NOT NULL,
raza_id integer NOT NULL,
estado_reproductivo character varying(80) NOT NULL,
estado_leche character varying(80),
CONSTRAINT ganado_pk PRIMARY KEY (ganado_id),
CONSTRAINT diio_fk FOREIGN KEY (diio_id)
    REFERENCES agroapp.diio (diio_id) MATCH SIMPLE
    ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT fundo_fk FOREIGN KEY (fundo_id)
    REFERENCES agroapp.fundo (fundo_id) MATCH SIMPLE
    ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT raza_fk FOREIGN KEY (raza_id)
    REFERENCES agroapp.raza (raza_id) MATCH SIMPLE
    ON UPDATE NO ACTION ON DELETE NO ACTION
)

【问题讨论】:

标签: postgresql indexing casting postgresql-performance


【解决方案1】:

很可能是因为强制转换使在agroapp.ganado_fundo.created列上使用索引的选项无效

猜测(由于缺乏信息)gf.created 的类型为 timestamp with time zone(或 timestamp),替换

AND gf.created::DATE <= '20181030'::DATE

与:

AND gf.created < '2018-10-31'::timestamp  -- match the data type of the column!

实现相同的结果,但支持索引。

如果您使用timestamtptz 操作,请注意日期的含义:它取决于当前时区。详情:

【讨论】:

  • 您对匹配数据类型是正确的。唯一的问题是 gf.created 可以是“2018-10-30 16:54:23.2562”之类的东西,我需要删除小时以使其与日期匹配。
  • 仔细观察:通过与&lt; '2018-10-31'::timestamp&lt; '2018-10-31 00:00'::timestamp 的缩写,即下一天的 00:00 小时)进行比较,已经解决了这一问题。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-24
  • 1970-01-01
  • 1970-01-01
  • 2013-09-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多