加快在 PostgreSQL 中的搜索

Posted

技术标签:

【中文标题】加快在 PostgreSQL 中的搜索【英文标题】:Speed up the search in a PostgreSQL 【发布时间】:2020-09-05 05:46:24 【问题描述】:

如何加快 PostgreSQL 数据库中的搜索速度?共有三个表:table_a、table_b、table_c。 table_a 有450 000 记录,table_b 有8 300 000 记录,table_c 有1 180 000 的问题 记录。 此查询需要等待大约 15 分钟:

    select  table_c.* from table_c
left join table_b on table_b.id = table_c.table_b_id
left join table_a on table_a.id = table_b.table_a_id
where table_a.id = 1

行数不能超过500。当我设置上限为500时,查询时间变成1秒以内。

创建信息:

CREATE TABLE table_a
(
  id serial NOT NULL,
  latitude numeric(10,8) NOT NULL,
  longitude numeric(11,8) NOT NULL,
  CONSTRAINT table_a_pkey PRIMARY KEY (id),
)

CREATE TABLE table_b
(
  id serial NOT NULL,
  table_a_id integer,
  CONSTRAINT table_b_pkey PRIMARY KEY (id),
  CONSTRAINT table_b_table_a_id_fkey FOREIGN KEY (table_a_id)
      REFERENCES table_a (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)

CREATE TABLE table_c
(
  id serial NOT NULL,
  table_b_id integer,
  geom geometry(MultiPolygon,4326),
  CONSTRAINT table_c_pkey PRIMARY KEY (id),
  CONSTRAINT table_c_table_b_id_fkey FOREIGN KEY (table_b_id)
      REFERENCES table_b (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)

其他信息:

操作系统 Windows 7 内存 4 GB CPU 2 - 3Ghz Postgres 9.4.26 64 位

【问题讨论】:

edit您的问题并添加使用explain (analyze, buffers, format text)生成的execution plan(不是只是一个“简单”解释)为formatted text,并确保保留计划的缩进。粘贴文本,然后将``` 放在计划前一行和计划后一行。还请包括所有索引的完整create index 语句。最好先打开track_io_timing(需要超级用户访问权限) 您可能需要考虑升级到受支持和维护的 Postgres 版本。 9.4 是no longer supported,自 2016 年以来性能也有了显着提升。一般来说,只有 4GB 的计算机并不适合用作数据库服务器(很可能还有慢速硬盘)。 @a_horse_with_no_name。缺少 indexex。创建的索引可以解决所有问题。谢谢。 【参考方案1】:

首先,不需要left joins,因为where 子句无论如何都会将它们变成内部连接。所以将查询重写为:

select  c.*
from table_c c join
     table_b b
     on b.id = c.table_b_id join
     table_a a
     on a.id = b.table_a_id
where a.id = 1;

那么以下索引应该会有所帮助:table_a(id)table_b(table_a_id, id)table_c(table_b.b_id)

其实查询可以简化,因为table_a的id在table_b

select  c.*
from table_c c join
     table_b b
     on b.id = c.table_b_id 
where b.table_a_id = 1;

此查询不需要第一个索引。

最后,如果此查询可能返回重复项并且您不想要它们,那么您可以考虑:

select c.*
from table_c c
where exists (select 1
              from table_b b
              where b.id = c.table_b_id and b.table_a_id = 1
             );

【讨论】:

以上是关于加快在 PostgreSQL 中的搜索的主要内容,如果未能解决你的问题,请参考以下文章

Postgres中的物化节点之sort节点

:: 在 PostgreSQL 中做啥? [复制]

PostgreSQL在没有时区的时间戳类型的表中搜索

postgres 错误:Postgresql 11.6 中的列不存在错误

如何加快计算 PostgreSQL 表中的行数?

Django trigram_similar搜索没有返回结果(带有Postgresql 10.5后端的Django 2.1)