因为在 Debian stable 上安装非常容易,所以我决定使用 PostgreSQL 9.6 为我需要处理的一些数据构建一个数据仓库。第一步是以最少的转换将数据加载到数据库中,主要是纠正一些已知的格式错误以及布尔值的表示方式。我已经检查过这些更正是否有效:将n
行写入磁盘所花费的时间与n
.
但是,使用 PostgreSQL 批量加载这些数据COPY FROM
(无论如何;\copy
、或 psycopg2copy_expert
或COPY FROM '/path/to/data.csv'
)需要超线性的时间量。渐近时间复杂度似乎比O(exp(sqrt(n)))
. 这就是我已经:
- 将隔离级别设置为
READ UNCOMMITTED
, 和 - 将主键约束设置为
DEFERRED
.
这是我看到的最严重的违规者之一,一个 17M 行的表:
禁用fsync
会使进程加快 10 倍,因此 I/O 显然是一个巨大的瓶颈。然而,除此之外,时间行为并没有太大变化:
当我使用代理键而不是业务键时,这个问题完全消失了:当我使用自动递增的整数列作为主键时,摄取又需要时间,这正是我想要的。因此,我不仅对我的问题有一个完全有效的解决方法,而且我还知道复杂的主键是罪魁祸首(业务键通常是一个短 VARCHAR 列的元组)。Θ(n)
但是,我想了解当 PostgreSQL 以业务键为键时,为什么要花这么长时间来摄取数据,以便我更好地了解我的工具。特别是,我不知道如何调试这个摄取过程,因为EXPLAIN
在COPY
. 可能是复合主键将数据排序到存储中需要更长的时间,或者这是由于索引,或者主键约束实际上仍然是NOT DEFERRED
;如果解决方法不是那么有效,或者由于其他原因不受欢迎,我如何才能发现这里实际发生了什么?