为什么 Postgres 需要这么长时间才能返回序列号?

AKW*_*KWF 5 postgresql performance postgresql-performance

我有一个应用程序可以批量加载到一个大表(1 亿行)中。我正在使用 Postgres 的COPY FROM功能从平面文件加载数据。目标表的主键为id

为了让批量插入工作,我使用以下方法为加载文件中的每一行创建了 id:

 SELECT  nextval('apps_id_seq'::regclass)
 FROM    "apps"
 ORDER   BY "apps"."id" ASC
 LIMIT   1 
Run Code Online (Sandbox Code Playgroud)

不幸的是,我没有看到这个查询花费的时间超过 150 秒。它会导致大量备份,因为其中一些文件包含数万行。

然而,当我在命令行运行它时,我得到了千分之一毫秒的返回结果。这是一个explain analyze

                                                            QUERY PLAN                                                                
------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=0.57..0.64 rows=1 width=4) (actual time=0.016..0.017 rows=1 loops=1)
   ->  Index Only Scan using apps_pkey on apps  (cost=0.57..15886651.40 rows=228128608 width=4) (actual time=0.015..0.015 rows=1 loops=1)
     Heap Fetches: 0
 Total runtime: 0.030 ms
Run Code Online (Sandbox Code Playgroud)

可能是什么导致了延迟?服务正在报告延迟NewRelic

Erw*_*ter 2

我认真研究了你的问题,但无法理解你所描述的过程。(您可能会进一步研究描述。)

既然可以让 Postgres 自动生成序列号,为什么还要手动生成序列号呢?根据文档:

如果指定了列列表,COPY则仅将指定列中的数据复制到文件或从文件中复制。如果表中有任何列不在列列表中,COPY FROM则将为这些列插入默认值

大胆强调我的。列的默认值serial是其序列中的下一个 id。

您确定您没有以非常昂贵的方式做大量冗余工作吗?

  • 这样做的唯一合理原因是无间隙序列。但你当然不会使用“nextval”。顺便说一句,9.6 应该包含一个内置的无间隙序列生成器,这样您就可以通过所有适当的锁定从“nextval”获得无间隙序列。 (3认同)