在 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 毫秒内完成。
有两件事可能有助于解释您观察到的问题:
你对两个表进行交叉连接,因为你没有WHERE
连接它们的条件,即aduser
中的每一行与每一行相结合在符合条件的 dcdocument
中。
这导致 208 * 591 = 122928 个结果行,这可能不是您想要的。
您一定是在使用像 pgAdmin 这样的客户端,它需要很长时间才能显示从查询返回的许多结果行。
解决方案可能是在 WHERE
或 JOIN
子句中添加缺少的条件。
我有以下查询,我想对其进行优化,执行时间为 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 毫秒内完成。
有两件事可能有助于解释您观察到的问题:
你对两个表进行交叉连接,因为你没有
WHERE
连接它们的条件,即aduser
中的每一行与每一行相结合在符合条件的dcdocument
中。这导致 208 * 591 = 122928 个结果行,这可能不是您想要的。
您一定是在使用像 pgAdmin 这样的客户端,它需要很长时间才能显示从查询返回的许多结果行。
解决方案可能是在 WHERE
或 JOIN
子句中添加缺少的条件。