这里有许多因素在起作用:
网络延迟如果服务器是远程服务器,则您可能正在“支付”每个语句的固定时间“价格”,例如50毫秒(1/20秒)。对于某些云托管数据库,甚至更多。由于下一个插入 *** 作要等到最后一个 *** 作成功完成后才能开始,所以这意味着您的
最大 插入速率是每秒1000 /来回延迟毫秒数行。延迟为50毫秒(“
ping时间”),即20行/秒。即使在本地服务器上,此延迟也不为零。Wheras
COPY只是填充TCP发送和接收窗口,并且以DB可以写入它们并网络可以传输它们的速度来传输流。它不受延迟的影响很大,并且可能每秒在同一网络链接上插入数千行。PostgreSQL中的每个陈述式成本
在PostgreSQL中解析,计划和执行语句也有成本。它必须要加锁,打开关系文件,查找索引等。
COPY在开始时尝试一次完成所有这些 *** 作,然后只专注于尽可能快地加载行。任务/上下文切换成本
由于 *** 作系统必须在您的应用程序准备和发送时在等待行的postgres之间切换,然后在postgres处理该行的同时等待postgres的响应的应用程序之间切换,因此还要支付更多的时间成本。每次从一个切换到另一个时,都会浪费一点时间。当进程进入和离开等待状态时,可能会浪费更多时间来挂起和恢复各种低级内核状态。
错过了COPY优化最重要的是,
COPY有一些优化可以用于某些负载。例如,如果没有生成的键并且任何默认值都是常量,它可以预先计算它们并完全绕过执行程序,从而将数据快速加载到较低级别的表中,从而完全跳过了PostgreSQL的部分正常工作。如果您
CREATETABLE或
TRUNCATE与您处于同一事务中
COPY,则可以绕过多客户端数据库中所需的常规事务簿记,从而做更多的技巧来加快加载速度。
尽管如此,PostgreSQL
COPY仍然可以做更多的事情来加快速度,这是它尚不知道如何做的事情。如果您要更改表的一定比例,它可能会自动跳过索引更新,然后重建索引。它可以批量进行索引更新。还有更多。提交费用
最后要考虑的一件事是提交成本。对于您来说,这可能不是问题,因为
psycopg2默认情况下会打开一个事务,直到您告知后才提交。除非您告诉它使用自动提交。但是对于许多数据库驱动程序,自动提交是默认设置。在这种情况下,您将每次执行一次提交
INSERT。这意味着一个磁盘刷新,服务器确保将内存中的所有数据写出到磁盘上,并告诉磁盘将自己的缓存写出到持久性存储中。这可能需要很
长时间 时间,并且因硬件而异。我的基于SSD的NVMe BTRFS笔记本电脑只能执行200 fsyncs
/秒,而不是每秒300,000次非同步写入。因此它只会加载200行/秒!某些服务器只能执行50 fsync
/秒。有些可以做到20,000。因此,如果必须定期提交,则尝试分批加载和提交,进行多行插入等。由于最后
COPY只提交一次,因此提交成本可以忽略不计。但这也意味着
COPY无法从数据中途的错误中恢复;它会取消整个批量加载。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)