Db2 for i - RUNSQLSTM - 插入包含数百万条记录的脚本

时间:2015-03-10 16:06:24

标签: sql jdbc db2 ibm-midrange

我试图运行一个包含数百万个INSERT的大型SQL脚本(对于测试,我将其限制为100,000行)。

我尝试了很多不同的方法:CPYFRMSTMF,FTP,JDBC客户端,客户端访问数据传输,IBM Data Studio,来自System i Navigator的SQL脚本......只是想知道哪一个更好。 其中一种方法是使用RUNSQLSTM运行脚本(它位于IFS上)。

但是,开始插入记录需要很长很长时间。 在开始插入记录之前,该命令正在执行一些先前的任务。

我在COMMIT参数上选择了* NONE,以及OPTION中的NOLIST(我不需要假脱机文件)。

但我不知道为什么需要这么长时间。

一个令人难以置信的事情(在我的测试中,我已尝试过100,000条记录)运行脚本只需1分钟:如果我从使用JDBC连接iSeries的软件执行它,则需要40秒。

有什么想法吗?

谢谢!

4 个答案:

答案 0 :(得分:2)

试图了解情况。是否有数百万行INSERT INTO ...语句?如果是这样,那么这可能是延迟开始实际插入的原因 - 实际上必须读取巨型脚本文件的所有行。

是否有一个INSERT语句执行类似INSERT INTO ... SELECT FROM ... WHERE ...?如果是这种情况,那么当优化器完成读取源行的工作时可能存在延迟。

还有别的吗?您能否分享一下脚本和所涉及的表格中的确切SQL语句?

答案 1 :(得分:1)

如果从脚本运行,最有可能的主要改进是使用阻塞的INSERT。也就是insert many rows with each INSERT statement

以下是我运行的低效脚本中的前三个INSERT语句:

INSERT INTO MYLIB/MYDATA VALUES(10, 1, 'N')
;
INSERT INTO MYLIB/MYDATA VALUES(11, 1, 'Y')
;
INSERT INTO MYLIB/MYDATA VALUES(11, 2, 'Y')
;

完整脚本包含100,000个INSERT语句。两次运行给出了20:34和20:32的时间。

我对脚本进行了编辑,以创建一个更高效的示例。我更改了每个语句终结符,以便每个语句插入另外四行。前三行看起来像这样:

INSERT INTO MYLIB/MYDATA VALUES(10, 1, 'N')                               
,(11, 1, 'Y'),(13, 1, 'N'),(14, 1, 'N'),(14, 2, 'Y');
INSERT INTO MYLIB/MYDATA VALUES(11, 1, 'Y')
,(11, 1, 'Y'),(13, 1, 'N'),(14, 1, 'N'),(14, 2, 'Y');
INSERT INTO MYLIB/MYDATA VALUES(11, 2, 'Y')
,(11, 1, 'Y'),(13, 1, 'N'),(14, 1, 'N'),(14, 2, 'Y');

我修改了脚本,因此只有20,000个INSERT语句(仍然插入100,000行,一次五行)。

两次运行时间分别为1:51和2:09,相同行数的运行时间基本上减少了90%。如果我一次生成了10行或50行的INSERT,那么可能会有更好的改进。

通过一些简单的格式化可以看到表单更好:

INSERT INTO MYLIB/MYDATA VALUES(10, 1, 'N'),
                               (11, 1, 'Y'),
                               (13, 1, 'N'),
                               (14, 1, 'N'),
                               (14, 2, 'Y');
INSERT INTO MYLIB/MYDATA VALUES(11, 1, 'Y'),
                               (11, 1, 'Y'),
                               (13, 1, 'N'),
                               (14, 1, 'N'),
                               (14, 2, 'Y');
INSERT INTO MYLIB/MYDATA VALUES(11, 2, 'Y'),
                               (11, 1, 'Y'),
                               (13, 1, 'N'),
                               (14, 1, 'N'),
                               (14, 2, 'Y');

您可以自动编辑脚本以获得类似的结果。

答案 2 :(得分:0)

对于简单地插入数据,最快的方法是使用AS400命令 并将数据平面复制到文件中。使用sql的最快插入将是一个多插入。当你* DLY索引维护时,这两种方法都会更快。

以下是如何进行平面文件复制的方法。这是数据在文本文件中与表的数据布局完全对齐的位置。表a是txt文件。

CPYF FROMFILE(A)       
     TOFILE(B)         
     MBROPT(*ADD)      
     FMTOPT(*NOCHK)

通过将基于物理文件(表)的每个逻辑文件(索引)的访问路径维护设置为* DLY,可以使批量插入在iseries上更快。忽略任何未更改访问路径的警告消息。这是因为索引是一个唯一键,无法关闭(* DLY)。您需要对表和索引的独占访问才能使用此过程。

CHGLF file(myLib/myFile1) MAINT(*DLY)
CHGLF file(myLib/myFile2) MAINT(*DLY)
CHGLF file(myLib/myFile3) MAINT(*DLY)
CHGLF file(myLib/myFile4) MAINT(*DLY)

在这里插入bluk插件。完成后,根据物理文件(表)将访问路径维护更改回每个逻辑文件(索引)的* IMMED。

CHGLF file(myLib/myLogicalFile1) MAINT(*IMMED)
CHGLF file(myLib/myLogicalFile2) MAINT(*IMMED)
CHGLF file(myLib/myLogicalFile3) MAINT(*IMMED)
CHGLF file(myLib/myLogicalFile4) MAINT(*IMMED)

您可以使用DSPDBR显示数据库关系命令获取基于物理文件(表)的所有逻辑文件(索引)的列表。

DSPDBR FILE(myLib/myTable)

答案 3 :(得分:0)

谢谢,@ danny117 !!! 这样可行!! 但是,使用RUNSQLSTM我将使用shell命令DB2 Utility。它确实很快,虽然它有一些问题(错误控制)。 A bit more info

我使用它的方式非常简单: 我在IFS(QSH)上创建了一个shell批处理文件。在文件中,您只需要一个句子:

db2 -t -v -f $ * LIB

(其中LIB是您正在运行的脚本的目标LIB)。 并且,我使用参数调用它,在这种情况下,只是我想要运行的脚本的路径。

当然,它为您提供了很多选项,因为批处理文件可以完成许多不同的任务。 我使用STRQSH命令从CL运行所有内容。 这是我的CLP来源:

         DCL        VAR(&CONF1) TYPE(*CHAR) STG(*AUTO) LEN(250) +
                      VALUE('/BATCH/Batch_pruebas_migracion/bin/rundb2.s+
                      h +
                      usr/INIGREDI/PRUEBAS_MIG/PRUMIG_opt-1000000.SQL')

         CLRPFM     INIGREDI/PRUMIG


         OVRPRTF    FILE(QPRINT) OUTQ(QEZJOBLOG) MAXRCDS(*NOMAX) +
                      SPLFNAME(PRUMIG) EXPDATE(*DAYS) DAYS(7)

         STRQSH     CMD(&CONF1)             

我会更多地解释一下CLP。 & CONF1包含我想用STRQSH执行的命令。您需要编写shell批处理文件的完整路径。 并且,在这种情况下,然后,在空格后,参数。在这种情况下,此参数是我要运行的SQL脚本的路径。 我按照你的建议,优化了该脚本(让我说,优化它并不总是一个好主意,它取决于你想要插入的记录的内容和大小)。

'OVRTPRTF'已完成,因为运行DB2实用程序会创建一个假脱机文件。它真的很大,因为它至少包含一行每个句子进入sql脚本(你可以改变详细模式,但最小,1行)。 并且,为了不忘记我的系统上的大卷轴文件,它在7天后编程了其自动删除。

这非常快,特别是与RUNSQLSTM相比。 虽然FTP或CPYFRMSTMF更快,但使用数字字段管理起来有点困难,特别是当它们包含负数或十进制数时。 (但这是另一个历史)。

而且,正如@ danny117所说,优化SQL脚本时的改进真的令人难以置信。在某些情况下,我有2000%的速度差异。 如果您从目标文件中删除日记,这也很重要。或者,当然,逻辑文件,约束或任何意味着在传输过程中对数据库引擎有更多工作的东西。

感谢大家的帮助。如你所见,我从不同的答案中提出了我的问题。 如果您需要有关我如何达到目标的任何进一步解释,请不要犹豫,并要求!