4

我正在进行一个项目,该项目涉及尝试从价值 70GB 的 xml 文档中获取大量信息并将其加载到关系数据库(在本例中为 postgres)我目前正在使用 python 脚本和 psycopg2 来执行此插入和诸如此类的操作. 我发现随着某些表中的行数增加。(其中最大的行数约为 500 万行)脚本(插入)的速度已经慢到爬行。曾经需要几分钟的事情现在需要大约一个小时。

我能做些什么来加快速度?我在这个任务中使用 python 和 psycopg2 有错吗?我可以对数据库做些什么来加快这个过程。我觉得我正在以完全错误的方式处理这件事。

4

7 回答 7

2

Considering the process was fairly efficient before and only now when the dataset grew up it slowed down my guess is it's the indexes. You may try dropping indexes on the table before the import and recreating them after it's done. That should speed things up.

于 2011-02-11T12:39:49.537 回答
1

wal_buffers 和 checkpoint_segments 的设置是什么?对于大型交易,您必须调整一些设置。检查手册

考虑一下PostgreSQL 9.0 High Performance一书,除了数据库配置来获得高性能,还有很多需要调整的地方。

于 2011-02-11T12:27:46.673 回答
1

在文档的填充数据库部分中有关于此主题的提示列表。您也可以使用Tuning Your PostgreSQL Server中的提示来提高总体性能。

检查外键的开销可能会随着表大小的增加而增加,这会变得更糟,因为您一次加载一条记录。如果您要加载 70GB 的数据,在加载期间删除外键,然后在导入时重建它们会快得多。如果您使用单个 INSERT 语句,则尤其如此。切换到 COPY 也不能保证改进,因为挂起的触发器队列是如何管理的——第一个文档链接中讨论了那里的问题。

从 psql 提示符中,您可以找到强制执行外键的约束的名称,然后使用该名称删除它,如下所示:

\d tablename
ALTER TABLE tablename DROP CONSTRAINT constraint_name;

完成加载后,您可以使用以下方式将其放回:

ALTER TABLE tablename ADD CONSTRAINT constraint_name FOREIGN KEY (other_table) REFERENCES other_table (join_column);

找出用于还原的确切语法的一个有用技巧是在您的数据库上执行pg_dump --schema-only 。其中的转储将向您展示如何重新创建您现在拥有的结构。

于 2011-02-15T17:03:50.077 回答
1

看看http://pgbulkload.projects.postgresql.org/

于 2011-02-13T02:35:00.823 回答
1

我会尝试使用COPY而不是插入。这就是备份工具用于快速加载的方法。

检查此表中的所有外键是否在目标表上都有相应的索引。或者更好 - 在复制之前暂时放下它们并在之后重新创建。

将 checkpoint_segments 从默认的 3(这意味着 3*16MB=48MB)增加到更高的数字 - 例如尝试 32 (512MB)。确保您有足够的空间来存储这么多额外的数据。

如果您有能力在系统崩溃或电源故障的情况下从头开始重新创建或恢复数据库集群,那么您可以使用“-F”选项启动 Postgres,这将启用 OS 写入缓存。

于 2011-02-11T14:22:26.010 回答
0

前 5 百万行没什么,插入的差异不应该改变是 100k 还是 1 mil;1-2 个索引不会减慢它的速度(如果填充因子设置为 70-90,考虑到每个主要导入是 table 的 1/10)。

带有 PSYCOPG2 的 python 非常快。一个小技巧,你可以使用数据库扩展 XML2 来读取/处理数据

来自https://dba.stackexchange.com/questions/8172/sql-to-read-xml-from-file-into-postgresql-database的小例子

duffymo 是对的,尝试以 10000 个插入块的形式提交(仅在最后或每次插入之后提交非常昂贵)如果您进行大量删除和更新,autovacuum 可能会膨胀,您可以在开始时暂时关闭它某些表。根据您的服务器可用资源设置work_mem和maintenance_work_mem ...对于插入,增加wal_buffers,(9.0及更高版本默认设置为-1)如果您使用版本8 postgresql,您应该手动增加它 cud也关闭fsync并进行测试wal_sync_method(如果发生突然的电源故障或硬件崩溃,请谨慎更改这可能会使您的数据库崩溃不安全)

尝试删除外键、禁用触发器或设置触发器不运行/跳过执行的条件;

对插入、强制转换变量使用准备好的语句

你 cud 尝试将数据插入到未记录的表中以临时保存数据

插入是否具有来自子查询、函数等的条件或值?

于 2013-03-01T14:37:39.017 回答
0

我会查看回滚日志。如果您在一笔交易中进行此操作,它们必须变得相当大。

如果是这种情况,也许您可​​以尝试提交较小的事务批量大小。将其分成更小的记录块(1K、10K、100K 等),看看是否有帮助。

于 2011-02-11T12:16:40.180 回答