在 PostgreSQL 中检查行是不是存在非常慢

Posted

技术标签:

【中文标题】在 PostgreSQL 中检查行是不是存在非常慢【英文标题】:Checking if a row exists is very slow in PostgreSQL在 PostgreSQL 中检查行是否存在非常慢 【发布时间】:2020-12-03 16:31:17 【问题描述】:

我有一个product 表,它有一个索引manufacturer_id。该表有 30M 行。我想检查表中是否存在特定行。我使用的查询:

select exists(select 1 from product where manufacturer_id = '0');

select 1 from product where manufacturer_id = '0' fetch first row only;

select 1 from product where manufacturer_id = '0' limit 1;

每个查询需要 4 分钟。表中有 12M 行带有manufacturer_id = '0'。但是,如果我使用 manufacturer_id = '1234567'(表中有 2 行)运行相同的查询,它会在 250 毫秒内返回结果。

我希望检查行的存在不会花费很长时间。或者,我是不是弄错了,考虑到桌子的容量,花那么长时间是正常的?如果不正常,如何提高性能?

执行计划:

Result  (cost=0.07..0.08 rows=1 width=1) (actual time=0.015..0.016 rows=1 loops=1)
  Buffers: shared hit=1
  InitPlan 1 (returns $0)
    ->  Seq Scan on product  (cost=0.00..914306.95 rows=12306868 width=0) (actual time=0.014..0.014 rows=1 loops=1)
          Filter: ((manufacturer_id)::text = '0'::text)
          Buffers: shared hit=1
Planning Time: 0.093 ms
Execution Time: 0.036 ms

创建索引语句:(这是除主键之外的唯一索引)

create index product_manufacturer_id
    on product (manufacturer_id);

ma​​nufacturer_id: varchar 类型和indexed 列。

Postgres 版本:12

【问题讨论】:

manufacturer_id 是什么数据类型?如果那是intbigint,则必须将其与数字进行比较。 '1234567' 是一个字符串,因此无法使用索引,请改用 where manufacturer_id = 1234567。这在使用explain (analyze) 生成的执行计划中很容易看到 该列是varchar 类型并且已经有一个index。我编辑了问题。 那么请edit您的问题并添加使用explain (analyze, buffers, format text)生成的慢查询execution plan(not 只是一个“简单”的解释)作为formatted text 并确保保留计划的缩进。粘贴文本,然后将``` 放在计划前一行和计划后一行。还请包括所有索引的完整 create index 语句。 计划显示运行该查询需要 0.036 毫秒秒 - 这甚至比您提到的 4 分钟还差 请向我们展示表和索引的完整 ddl。加上解释分析 【参考方案1】:

您想要在manufacturer_id 上建立索引:

create index idx_product_manufacturer_id on product(manufacturer_id)

您可能需要manufacturer_id 之后的其他键来支持其他查询。但是manufacturer_id 必须是第一列

此外,您需要注意类型。所以,你希望比较使用相同的类型——双引号意味着比较是字符串而不是整数。并且即使它们都是字符串,如果排序规则不同,也可能无法使用索引。

没有索引,Postgres 必须扫描表以找到匹配项。显然,'1234567' 会以 Postgres 扫描的任何顺序快速显示。但是'0' 没有。

索引解决了这个问题。而且它也有助于加入manufacturers 表。

【讨论】:

该列是varchar 类型并且已经有一个index。我编辑了问题。

以上是关于在 PostgreSQL 中检查行是不是存在非常慢的主要内容,如果未能解决你的问题,请参考以下文章

检查 postgresql 的返回查询中是不是存在值

检查 json 类型列 PostgreSQL 中是不是存在字段

编辑大代码时Rstudio非常慢

检查 Azure 存储中是不是存在 blob

一次PostgreSQL行估算偏差导致的慢查询分析

Postgresql 日期函数扫描每个分区中的每一行并且执行速度非常慢