在 PostgreSQL 中进行简单 select 优化

Simple select to optimize in PostgreSQL

我有以下查询,我想对其进行优化,执行时间为 4 秒,行数为 122,928,但表之间没有任何人 link。

有什么办法可以优化吗?我需要相同数量的行,但执行时间需要大大减少。

select dc.cddocument, us.cduser
from dcdocument dc, aduser us
 WHERE  (dc.FGUSECATACCESSROLE <> 1 OR dc.FGUSECATACCESSROLE IS NULL);

查询计划

teste20=# explain analyze select dc.cddocument, us.cduser from dcdocument dc, aduser us WHERE  (dc.FGUSECATACCESSROLE <> 1 OR dc.FGUSECATACCESSROLE IS NULL);
                                                           QUERY PLAN                                            
---------------------------------------------------------------------------------
     Nested Loop  (cost=0.00..1584.32 rows=124110 width=8) (actual time=0.062..23.679 rows=122928 loops=1)
       ->  Seq Scan on aduser us  (cost=0.00..19.91 rows=591 width=4) (actual time=0.029..0.190 rows=591 loops=1)
       ->  Materialize  (cost=0.00..13.56 rows=210 width=4) (actual time=0.000..0.012 rows=208 loops=591)
             ->  Seq Scan on dcdocument dc  (cost=0.00..12.51 rows=210 width=4) (actual time=0.024..0.308 rows=208 loops=1)
                   Filter: ((fgusecataccessrole <> 1) OR (fgusecataccessrole IS NULL))
                   Rows Removed by Filter: 393
     Planning time: 0.474 ms
     Execution time: 27.183 ms
    (8 registros)

查询计划不显示执行的实时时间。

创建 TABLE dcdocument

CREATE TABLE public.dcdocument
(
    cddocument integer NOT NULL,
    cdcategory integer,
    dtdocument date,
    fgstatus integer,
    dssummary text COLLATE pg_catalog."default",
    nmtitle character varying(255) COLLATE pg_catalog."default",
    nmauthor character varying(255) COLLATE pg_catalog."default",
    iddocument character varying(50) COLLATE pg_catalog."default",
    dsdoccancel text COLLATE pg_catalog."default",
    fgusecataccessrole integer,
    cdcreatedby integer,
    nrhits integer,
    dtinsert date,
    dtupdate date,
    nmuserupd character varying(255) COLLATE pg_catalog."default",
    dtvalidity date,
    qtvalidity integer,
    fgtypevalid integer,
    cdprod integer,
    cdapprov integer,
    cdtemparchival integer,
    cdfavorite integer,
    fgoldstatus integer,
    CONSTRAINT pkdcdocument PRIMARY KEY (cddocument),
    CONSTRAINT fkdocumcdcreatedby FOREIGN KEY (cdcreatedby)
        REFERENCES public.aduser (cduser) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION
)
WITH (
    OIDS = FALSE
)
TABLESPACE pg_default;

ALTER TABLE public.dcdocument
    OWNER to postgres;
CREATE INDEX "TESTES"
    ON public.dcdocument USING btree
    (cddocument, fgusecataccessrole)
    TABLESPACE pg_default;
CREATE INDEX seixdoccataccessrole
    ON public.dcdocument USING btree
    (fgusecataccessrole)
    TABLESPACE pg_default;
CREATE INDEX seixdoccdcategory
    ON public.dcdocument USING btree
    (cdcategory)
    TABLESPACE pg_default;
CREATE INDEX seixdocumcdcreated
    ON public.dcdocument USING btree
    (cdcreatedby)
    TABLESPACE pg_default;
CREATE INDEX seixdocumentapprov
    ON public.dcdocument USING btree
    (cdprod, cdapprov)
    TABLESPACE pg_default;
CREATE INDEX seixdocumentfavori
    ON public.dcdocument USING btree
    (cdfavorite)
    TABLESPACE pg_default;
CREATE INDEX seixdocumentstatus
    ON public.dcdocument USING btree
    (fgstatus)
    TABLESPACE pg_default;
CREATE INDEX seixdocumtemparchi
    ON public.dcdocument USING btree
    (cdtemparchival)
    TABLESPACE pg_default;

创建 TABLE 广告用户

CREATE TABLE public.aduser
(
    cduser integer NOT NULL,
    idlogin character varying(50) COLLATE pg_catalog."default",
    iduser character varying(50) COLLATE pg_catalog."default",
    nmuser character varying(255) COLLATE pg_catalog."default",
    idpassword character varying(50) COLLATE pg_catalog."default",
    dsuseremail text COLLATE pg_catalog."default",
    fglanguage integer,
    fguserenabled integer,
    cdmailserver integer,
    cdleader integer,
    dtinsert date,
    dtupdate date,
    nmuserupd character varying(255) COLLATE pg_catalog."default",
    idphone character varying(50) COLLATE pg_catalog."default",
    dsuser text COLLATE pg_catalog."default",
    nmdomainuid character varying(255) COLLATE pg_catalog."default",
    nmcertserialnum character varying(255) COLLATE pg_catalog."default",
    flpublickey bytea,
    fgnotice integer,
    fgstatuslogin integer,
    flphoto bytea,
    fgaccessrestrict integer,
    fgalterpassword integer,
    nmviewmodules character varying(255) COLLATE pg_catalog."default",
    idpasswordvalid character varying(50) COLLATE pg_catalog."default",
    nmuseremail character varying(255) COLLATE pg_catalog."default",
    fgtheme integer,
    fghomepage integer,
    dsurlhomepage text COLLATE pg_catalog."default",
    cddashboard integer,
    cddashboardtab integer,
    fgdashdoshare integer,
    dtrequestrstpsw date,
    idhashpassword character varying(50) COLLATE pg_catalog."default",
    cdlastlicense integer,
    fgpwdversion integer,
    cdcustomization integer,
    nmhashlastsession character varying(255) COLLATE pg_catalog."default",
    fgtransfped integer,
    cdtransfpedto integer,
    fgcontactenable integer,
    fgcontactpopup integer,
    cdfavorite integer,
    fgedittoolbar integer,
    fgeditgrid integer,
    nmphotopath character varying(255) COLLATE pg_catalog."default",
    dtbirthday date,
    CONSTRAINT pkaduser PRIMARY KEY (cduser),
    CONSTRAINT fk__aduser__cdtransf__56764864 FOREIGN KEY (cdtransfpedto)
        REFERENCES public.aduser (cduser) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION,
    CONSTRAINT fk_userleader FOREIGN KEY (cdleader)
        REFERENCES public.aduser (cduser) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION
)
WITH (
    OIDS = FALSE
)
TABLESPACE pg_default;
ALTER TABLE public.aduser
    OWNER to postgres;
CREATE INDEX "TESTE2"
    ON public.aduser USING btree
    (cduser)
    TABLESPACE pg_default;
CREATE INDEX seixcdleader
    ON public.aduser USING btree
    (cdleader)
    TABLESPACE pg_default;
CREATE INDEX seixusercdmailserv
    ON public.aduser USING btree
    (cdmailserver)
    TABLESPACE pg_default;
CREATE INDEX seixusercdtransfpedto
    ON public.aduser USING btree
    (cdtransfpedto)
    TABLESPACE pg_default;
CREATE INDEX seixuserenabled
    ON public.aduser USING btree
    (fguserenabled)
    TABLESPACE pg_default;
CREATE INDEX seixuserfglanguage
    ON public.aduser USING btree
    (fglanguage)
    TABLESPACE pg_default;
CREATE INDEX seixusergnfavorite
    ON public.aduser USING btree
    (cdfavorite)
    TABLESPACE pg_default;
CREATE INDEX seixuseridlogin
    ON public.aduser USING btree
    (idlogin COLLATE pg_catalog."default")
    TABLESPACE pg_default;
CREATE INDEX seixusernmdomainuid
    ON public.aduser USING btree
    (nmdomainuid COLLATE pg_catalog."default")
    TABLESPACE pg_default;
CREATE INDEX seixusernmfgencdus
    ON public.aduser USING btree
    (nmuser COLLATE pg_catalog."default", iduser COLLATE pg_catalog."default", cduser, fguserenabled)
    TABLESPACE pg_default;

您的查询已经以最佳方式执行,并且在 27 毫秒内完成。

有两件事可能有助于解释您观察到的问题:

  1. 你对两个表进行交叉连接,因为你没有WHERE连接它们的条件,即aduser中的每一行与每一行相结合在符合条件的 dcdocument 中。

    这导致 208 * 591 = 122928 个结果行,这可能不是您想要的。

  2. 您一定是在使用像 pgAdmin 这样的客户端,它需要很长时间才能显示从查询返回的许多结果行。

解决方案可能是在 WHEREJOIN 子句中添加缺少的条件。