极慢的 Netezza(数据库)批量插入

Posted

技术标签:

【中文标题】极慢的 Netezza(数据库)批量插入【英文标题】:Extremely Slow Netezza (Database) Batch Inserts 【发布时间】:2015-10-12 16:25:08 【问题描述】:

我正在使用批量插入和准备好的语句将数据插入到 Netezza。但是,性能非常缓慢。以下是我的代码:

final int batchSize = 1000;
int count = 0;
for (final MyClass object: myList) 
    ps.setString(1, object.getOne());
    ps.setString(2, object.getTwo());
    ps.setString(3, object.getThree());
    ps.setString(4, object.getFour());
    ps.setString(5, object.getFive());
    ps.setString(6, object.getSix());
    ps.setString(7, object.getSeven());
    ps.setString(8, object.getEight());
    ps.setString(9, object.getNine());
    ps.setString(10, object.get10());
    ps.addBatch();
    if(++count % batchSize == 0) 
        ps.executeBatch();
    

ps.executeBatch(); // insert remaining records

有谁知道如何加快速度?

【问题讨论】:

“极慢”需要多长时间?您期望的加载时间是多少?将数据插入数据仓库需要时间。 第二个吉尔伯特的请求。您的这批 1000 批产品实际上是什么时候获得的? @GilbertLeBlanc 使用上面的代码,我每秒可以得到大约 1-2 行。 【参考方案1】:

插入语句批处理不会Netezza 上执行,每个查询的开销将限制这些操作的效率。我建议将您的数据转储到平面文件并执行nzload/external table insert 示例请参考Transient External Tables。

【讨论】:

使用瞬态外部表让它工作。谢谢!【参考方案2】:

您可能已经知道,Netezza JDBC 驱动程序可能会检测到批量插入,并在幕后将其转换为外部表加载。

从这里的示例运行时可以看出,使用非批处理准备语句的单例插入非常慢,而使用 executebatch 运行的插入会随着批处理大小快速向上扩展。

start of call to testSingletonInserts() with batchSize = 100
exec time for batch-size 100: 8193ms
end of call to testSingletonInserts()

start of call to testBatchInserts() with batchSize = 1000
exec time for batch-size 1000: 190ms
end of call to testBatchInserts()

start of call to testBatchInserts() with batchSize = 10000
exec time for batch-size 10000: 734ms
end of call to testBatchInserts()

start of call to testBatchInserts() with batchSize = 100000
exec time for batch-size 100000: 1763ms
end of call to testBatchInserts()

一般来说,我不建议批量小于 10,000。

一个重要的诊断点是检查 JDBC 跟踪或 Netezza 系统上的 pg.log,以验证是否正在为您隐式调用外部表。

如果您看到这样的条目,那么您没有通过 JDBC 驱动程序获得隐式外部表的好处。

2015-08-08 12:52:50.640127 EDT [13898]  DEBUG:  QUERY: insert into testload (c1,c2) values (next value for testload_seq, 96)

如果您看到这样的条目,那么您将获得一个外部表。

2015-08-08 12:52:51.078404 EDT [13898]  DEBUG:  QUERY: CREATE EXTERNAL TABLE bulkETL_13898_0 ( c0 nvarchar(5) )  USING (  DATAOBJECT('/tmp/junk')  REMOTESOURCE 'jdbc'  DELIMITER '     '  ESCAPECHAR ''\'  CTRLCHARS 'YES'  CRINSTRING 'YES'  ENCODING 'INTERNAL'  MAXERRORS 1 QUOTEDVALUE 'YES' );
2015-08-08 12:52:51.086081 EDT [13898]  DEBUG:  QUERY: insert into testload (c1,c2) values (next value for testload_seq,bulkETL_13898_0.c0)
2015-08-08 12:52:51.101234 EDT [13898]  DEBUG:  transaction 1411711 started dbos txid 0x3dc5c

如果您发现批处理执行没有隐式外部行为,请尝试确保在您的连接上关闭自动提交。

conn.setAutoCommit(false);

【讨论】:

我只有 32k 行,即使将批处理大小设置为 10k,按照我的速度也需要几个小时才能完成。 在这种情况下,您肯定不会得到隐式的外部表行为。也许是因为启用了自动提交? @JohnRoberts 我面临同样的问题,我不得不插入数百万条记录,并且我尝试使用 10 K 和 100 K 的批量大小。仍然需要几个小时才能完成。自动提交是错误的。我应该怎么做才能获得隐式外部表行为?

以上是关于极慢的 Netezza(数据库)批量插入的主要内容,如果未能解决你的问题,请参考以下文章

android SQLite 批量插入数据慢的解决方案 (针对于不同的android api 版本)

mysql大量数据插入慢的问题

mysql批量插入数据

即使在批处理执行模式下,Netezza 批处理插入也非常慢

使用外部表逻辑在 netezza 中加载数据时出错

关于Redis批量写入的介绍