Vic*_*sto 5 postgresql performance index join postgresql-performance
我刚刚开始学习 Postgres,我遇到的情况是,根据我在表上执行 JOIN 的方式,性能和计划输出似乎真的很奇怪。
这些是与其索引一起使用的表:
create table escola
(
pk_codigo integer not null
constraint pk_escola
primary key,
nome varchar(100),
municipio varchar(150),
uf char(2),
cod_municipio integer,
uf_id integer default 0 not null
constraint fk_escola_uf_id
references tb_uf
)
;
create index idx_escola_uf
on escola (uf)
;
create index idx_escola_uf_id
on escola (uf_id)
;
create index idx_multi_escola_uf_pk
on escola (uf, pk_codigo)
;
create table if not exists candidato
(
pk_numero_inscricao bigint not null
constraint candidato_pk
primary key,
cod_municipio_residencia integer,
municipio_residencia varchar(150),
uf_residencia char(2),
uf_nascimento char(2),
situacao_conclusao numeric(1),
ano_concluiu smallint,
idade smallint,
sexo char,
fk_codigo_escola integer
constraint fk_candidato_codigo_escola
references escola,
uf_prova char(2)
)
;
create index if not exists idx_candidato_codigo_escola
on candidato (fk_codigo_escola)
;
create table tb_uf
(
uf varchar(2),
pk_id serial not null
constraint tb_uf_pkey
primary key
)
;
create unique index tb_uf_uf_uindex
on tb_uf (uf)
;
create unique index tb_uf_pk_id_uindex
on tb_uf (pk_id)
;
Run Code Online (Sandbox Code Playgroud)
和查询(有计划):
EXPLAIN ANALYZE
SELECT pk_numero_inscricao, pk_codigo
FROM escola e
JOIN candidato c
ON c.fk_codigo_escola = e.pk_codigo
WHERE e.uf = 'RJ'
;
Run Code Online (Sandbox Code Playgroud)
没有的时间EXPLAIN ANALYZE
:916ms 计划:https ://explain.depesz.com/s/M6B
EXPLAIN ANALYZE
SELECT pk_numero_inscricao, pk_codigo
FROM escola AS e
JOIN candidato AS c
ON c.fk_codigo_escola = e.pk_codigo
JOIN tb_uf AS u
ON e.uf_id = u.pk_id
WHERE u.uf = 'RJ'
;
Run Code Online (Sandbox Code Playgroud)
没有的时间EXPLAIN ANALYZE
:72ms 计划:https ://explain.depesz.com/s/E3MR
EXPLAIN ANALYZE
SELECT pk_numero_inscricao, pk_codigo
FROM escola AS e
JOIN candidato AS c
ON c.fk_codigo_escola = e.pk_codigo
WHERE e.uf_id = 19
;
Run Code Online (Sandbox Code Playgroud)
没有时间EXPLAIN ANALYZE
:961ms 计划:https ://explain.depesz.com/s/v67V
对我来说奇怪的事情是查询 1 和 3 比查询 2 慢,尽管查询 2 有一个额外的连接。有谁知道这可能是什么原因造成的?
我注意到,查询 1 和 3Index Scan
上的表candidato
也慢得多,这对我来说没有意义,因为最终结果是相同的。
另一点是EXPLAIN ANALYZE
在查询中增加了大量开销。
提前致谢!如果我需要提供更多信息,我可以根据需要编辑这篇文章!
当您注意到第一个和第三个查询从...获取 120 万行时,答案非常“可搜索”,candidato
只是为了从结果中排除其中的 90%。
第二个查询从 中返回 1 行tb_uf
,这会强制执行嵌套循环计划。
这意味着规划者对统计数据(预期结果计数)或成本(随机搜索)有错误的假设。您可以调整这些值:
https://www.postgresql.org/message-id/20060926193553.GA27268@oppetid.no
让 Postgresql 查询规划器使用带有索引的嵌套循环而不是散列连接
或手动强制嵌套循环。尽管我的直觉告诉我这里使用 Hash Join 应该会更好。
没有数据,我建议尝试以下之一:
set enable_mergejoin = off
Run Code Online (Sandbox Code Playgroud)WITH e AS (SELECT * FROM escola WHERE uf_id = 19) SELECT pk_numero_inscricao, pk_codigo FROM e JOIN candidato AS c ON c.fk_codigo_escola = e.pk_codigo
归档时间: |
|
查看次数: |
221 次 |
最近记录: |