为什么插入多行时 psql 查询需要更长的时间。为什么是非线性的

jon*_*odo 4 postgresql performance

因此,如果我将一行插入到 postgres 数据库中,则需要 18 毫秒。如果我在这样的循环中执行此操作:

INSERT INTO contacts (numbers)
SELECT  distinct array[
        (random() * 99999999)::integer,
        (random() * 99999999)::integer
    ]
  FROM generate_series(1,4000000) AS x(id);
Run Code Online (Sandbox Code Playgroud)

我改变插入的行数,时间是非线性的。这是数据:

-1 条记录 - 18 毫秒
-20k 条记录 - 36 秒
-50k 条记录 - 151 秒
-100k 条记录 - 750 秒

为什么这会呈指数级增长?我的数据库中需要 1000 万条记录进行负载测试,插入 50k 行然后再次重新插入 50k 似乎更快,因为 151 + 151 < 750

对这个主题的任何见解将不胜感激。我认为这是因为 postgres 将数据保存到回滚,以防查询严重失败或被用户取消,并且 postgres 不想“一半插入”整个请求。

Jos*_*kus 6

撇开 DISTINCT 导致一些奇怪行为的事实不谈,插入时间随着批量加载变大而变长的主要原因有两个:

  1. 随着 B 树索引变大并具有更多树级别,它们的更新效率会降低。因此,索引插入第 100 万个值所需的时间比插入第 10 个值的时间长。
  2. 在某些大小下,您超过了某些阈值,这会导致系统上出现额外的 IO,从而导致 IO 发生时的延迟。这些以复杂方式相互作用的阈值包括:
    • WAL 的大小,导致日志轮换
    • RAID 缓存的大小,降低到磁盘速度
    • Postgres 专用缓存的大小,导致刷新到 FS
    • FS 缓存的脏块刷新阈值的大小
    • 整个FS缓存的大小,导致紧急刷新