6

因为在 Debian stable 上安装非常容易,所以我决定使用 PostgreSQL 9.6 为我需要处理的一些数据构建一个数据仓库。第一步是以最少的转换将数据加载到数据库中,主要是纠正一些已知的格式错误以及布尔值的表示方式。我已经检查过这些更正是否有效:将n行写入磁盘所花费的时间与n.

但是,使用 PostgreSQL 批量加载这些数据COPY FROM(无论如何;\copy、或 psycopg2copy_expertCOPY FROM '/path/to/data.csv')需要超线性的时间量。渐近时间复杂度似乎比O(exp(sqrt(n))). 这就是我已经:

  • 将隔离级别设置为READ UNCOMMITTED, 和
  • 将主键约束设置为DEFERRED.

这是我看到的最严重的违规者之一,一个 17M 行的表:

当 fsync 打开时,行数的平方根与摄取时间的对数成比例

禁用fsync会使进程加快 10 倍,因此 I/O 显然是一个巨大的瓶颈。然而,除此之外,时间行为并没有太大变化:

当 fsync 关闭时,行数的平方根也与摄取时间的对数成正比

当我使用代理键而不是业务键时,这个问题完全消失了:当我使用自动递增的整数列作为主键时,摄取又需要时间,这正是我想要的。因此,我不仅对我的问题有一个完全有效的解决方法,而且我还知道复杂的主键是罪魁祸首(业务键通常是一个短 VARCHAR 列的元组)。Θ(n)

但是,我想了解当 PostgreSQL 以业务键为键时,为什么要花这么长时间来摄取数据,以便我更好地了解我的工具。特别是,我不知道如何调试这个摄取过程,因为EXPLAINCOPY. 可能是复合主键将数据排序到存储中需要更长的时间,或者这是由于索引,或者主键约束实际上仍然是NOT DEFERRED;如果解决方法不是那么有效,或者由于其他原因不受欢迎,我如何才能发现这里实际发生了什么?

4

0 回答 0