EMP*_*EMP 5 .net postgresql multithreading transactions thread-safety
我正在编写一个 .NET 4 应用程序,它将文件中的大量数据导入到 PostgreSQL 9.1 数据库中。分析显示,数据库调用实际 INSERT 数据占用了超过 90% 的时间。数据库服务器似乎受 CPU 限制 - 使用所有一个 CPU。
如果可能的话,我希望使用所有 CPU 更快地导入数据。输入文件可以在客户端上分成多个部分,因此这通常不会太难,但我想确保如果导入文件时发生任何错误,则数据库根本不会被修改。为了实现这一目标,我在一笔交易中完成了整个导入。
是否可以以某种方式向数据库服务器发送并发命令(以利用其所有 CPU),但仍确保整个导入成功或不进行任何更改?据我了解,不能从多个线程使用事务来同时运行多个命令,可以吗?我正在使用 Npgsql 作为 ADO.NET 提供程序,如果这有什么区别的话。
在Postgres 9.6之前,标准 PostgreSQL 无法通过多个线程并行处理事务,该功能被添加为“并行查询”。
不过,您的 INSERT 操作受 CPU 限制似乎很可疑。这里可能需要改进一些事情。具体如何将数据发送到服务器?基本上有四种将INSERT
数据存入表的方法:
COPY
是迄今为止最快的方法。
在大量/之后删除索引并在之后重新创建它们会更快。增量添加索引元组的效率比一次创建索引低得多。INSERT
COPY
触发器、约束或外键约束是可能减慢速度的其他因素。也许您可以在批量加载之前禁用/删除并在之后启用/重新创建?
还有许多设置可以产生重大影响。
您可以关闭fsync和synchronous_commit。(有风险!)
autovacuum
暂时禁用。ANALYZE
之后立即运行。(小心那些!)
阅读 Postgres Wiki 中有关批量加载和恢复以及调整 PostgreSQL 服务器的文章,尤其是有关checkpoint_segments和checkpoint_completion_target的段落。
该操作可能并不像看起来那样受 CPU 限制。看看PostgreSQL Wiki 中的这一段。
速度放缓的另一个原因可能是日志记录。例如,log_statement = all
会产生巨大的日志文件,但需要付出一定的代价,尤其是在单行插入时。
这是再次检查 PostgreSQL Wiki 中所有自定义设置的快速方法。
另一个加快速度的想法,特别是当你无法关闭 fsync 时。创建一个或多个空临时表,如下所示:
CREATE TEMP TABLE x_tmp AS SELECT * FROM real_tbl LIMIT 0;
Run Code Online (Sandbox Code Playgroud)
思考一下如何处理序列和其他默认值!
INSERT
将所有数据写入暂存表,然后通过一个命令写入目标表。索引和约束再次关闭,但时间要短得多。
INSERT INTO real_tbl SELECT * FROM x_tmp ORDER BY something;
DROP TABLE x_tmp;
Run Code Online (Sandbox Code Playgroud)
可能会快得多。确保为各种设置使用足够的 RAM。temp_buffers
特别看一下。
归档时间: |
|
查看次数: |
1986 次 |
最近记录: |