java shell 超时时间,关于Java:检查Oracle DB .shellscript作业中的大量记录超时

我正在从事一项日常自动化工作,该工作针对oracle数据库检查文本文件中的记录。

我们每天都会收到来自外部团队的文本文件,其中包含大约100,000条记录。文本文件将为unix格式,具有6列,由|分隔。符号。

例如,

HDR 1

home/sample/file|testvalue1|testvalue2|testval3|testval4|testval5

TRL

我需要检查oracle数据库中我的表中是否存在testval3和testval5中的值。该表有大约一千万条记录。

我目前正在通过shellscript处理它。在shellscript中,我正在读取文本文件并循环遍历每一行。在循环内部,我从每一行传递值,并对DB运行查询。如果记录在数据库中不存在,则必须将它们输出到一个csv文件中。使用以下查询:

select ‘testval3’,’testval5’ from dual

where not exists (select primarykeycolumn

from mytable where mycolumn=testval3 and mycolumn2=testval5)

由于输入文件有100000个条目,因此我的循环将运行查询100000次,并且每次它将检查具有1000万条记录的表。这使我的批处理作业要运行多个小时,我必须终止它。有没有更好的方法来处理这种情况?如果没有更好的方法可以通过shellscript进行操作,我也可以使用Java。

您正在使用UTL_FILE吗?您正在使用哪个Oracle版本?

看来您已经选择了效率最低的方法。您是否曾听说过SQL * Loader,外部表等?我的建议是首先在数据库中创建一个包含两列的表,然后使用SQL * Loader将文件加载到该表中。然后,使用单个查询,您可以提取所有需要的内容。与加载程序不同,外部表和UTL_FILE需要目录权限。如果可以轻松获得它,那就去吧。

@KaushikNayak他非常清楚自己的方式效率低下,这就是为什么他首先在这里提出问题。您只需省略前两个短语即可给出相同的值。

@Busybee:我发布了一个答案,可能是您正在寻找的东西。

@VinkoVrsalovic:您怎么知道它的"他"? 。此外,我不知道在Java标记下是否很少出现这样的问题,但是在Oracle中,SQL * Loader之类的东西是人们希望OP意识到的基本问题。我们需要连接一百万次的逻辑并没有给我留下深刻的印象。因此,问题是,为什么要使用它。

@KaushikNayak我不知道他们的性别,以他为默认。无论如何,我们都曾经是新手,面对新手实际上没有什么价值,他们可能很了解新手,他们很可能知道这一点以及寻求帮助的好处。我们需要更加欢迎,特别是关于网站上的新人。我就是这么说。如果您被不了解基本知识的人所冒犯,请跳过它!您不了解他们的情况,例如,这个人可能根本没有DBA或程序员的职责。

@VinkoVrsalovic:我通常想结束徒劳的论点,就是这样。但是,在结束之前,我只能说,如果我不欢迎新手,我什至不会发表评论或免费提供所有解决方案。

@kaushiknayak免费做事与欢迎无关。

@KaushikNayak对不起,我没有在原始问题中提及更多细节。我从事shellscript工作的原因是,最初的要求是大约1000条记录,并且从开发到生产之后,记录开始于100000条。创建临时表不是一开始就给我的选择,因为它具有还要经过一组额外的批准,这需要时间。

似乎最好的方法应该是通过创建登台表..因此,我将尝试这种方法。如果没有得到批准,我可以采用Vinko Vrsalovics的方法。感谢您的建议..!

Busybee:我认为您应该真正说服批准者/管理层使它为您工作,因为我认为,由于模块所有者之间的不合作,不应在效率和性能上做出妥协。您可能最终会找到解决方法,这些解决方法将来必定会引起麻烦。祝一切顺利!

以下是一种简单的解决方案,它可以确保不会出现超时,甚至您也不需要扫描数百万条记录以进行10万次。

一次设置:

创建临时临时表:

create table a_staging_table(

testvalue1 varchar2(255),

testvalue2 varchar2(255),

testval3 varchar2(255),

testval4 varchar2(255),

testval5 varchar2(255)

);

----重复过程

将您的" CSV / TEXT"数据加载到登台表中:

some_file_name.ctl:该文件包含以下加载数据命令。

load data

INFILE 'home/sample/file.csv'

INTO TABLE a_staging_table

APPEND FIELDS TERMINATED BY '|'

(testvalue1,testvalue2,testval3,testval4,testval5);

现在,运行SQL加载程序以将数据加载到暂存表形式。

sqlldr userid=dbUserName/dbUserPassword control=some_file_name.ctl log=some_file_name.log

您的数据已加载到登台表中。现在,将登台表和your_original_table结合起来以标识不存在的记录。

第一种方式:

使用SQL * PLUS从以下SQL假脱机输出:

select s.testval3,testval5

from (select distinct testval3,testval5

from a_staging_table) s

where not exists

(select 1

from your_original_table

where mycolumn1=s.testval3

and mycolumn2=s.testval5);

第二种方式:

Begin

for x in (

select s.testval3,testval5

from (select distinct testval3,testval5

from a_staging_table) s

where not exists

(select 1

from your_original_table

where mycolumn1=s.testval3

and mycolumn2=s.testval5)

) loop

DBMS_OUTPUT.put_line('testval3: '||x.testval3 || '      ------     '||'testval5: '||x.testval5);

--write all these values into another file saying that these are not matching values, using UTL_FILE.

--Then finally truncate the table"a_staging_table"

--so that this data will not available next time, and next time again process will run with different file

end loop;

无需再次建议循环。 OP可以将输出后台处理到csv。另外,group by可以替换为distinct

@KaushikNayak:感谢您指出,我用DISTINCT替换了GROUP BY

别客气。但是,我主要关心的是loop,这不是必需的。如果OP可以使用sqlloader,那么他们也可以使用shell脚本中的sqlplus命令行来简单地假脱机输出。

好的,我还将对此进行更新。

@KKK,感谢您的详细解释。抱歉,我没有首先提到这一点,testval5值将是一些用逗号分隔的值。例如,home / sample / file | testvalue1 | testvalue2 | testval3 | testval4 | test1,test2

例如,home / sample / file | testvalue1 | testvalue2 | testval3 | testval4 | test1,test2,test3。 test1,test 2,test 3的值是varchar2,我需要对照查询中提到的mycolumn2来检查它们。 original_table中的mycolumn2始终具有单个值,如test1或test2。有没有一种方法可以将值传递到登台表,例如将testvalue1,testvalue2,tesval3,testval4,test1作为1行,将testvalue1,testvalue2,tesval3,testval4,test2作为另一行,等等?

some_file_name.ctl中的@KKK,有没有办法从UNIX作业中单独传递文件名。每天会有一个文件名不同的文件,例如,以下内容位于文件ABCD_xx_xxdatetimestamp HDR 1 home / sample / file | testvalue1 | testvalue2 | testval3 | testval4 | test1,test2 TRL中。第二天,我们得到了另一个文件ABCD_x1x2_x3x4datetimestamp

对于动态文件名:stackoverflow.com/questions/27250002/

对于您在"注释"中提到的第一种情况,将其用作:将" and and mycolumn2 = s.testval5"都替换为" and mycolumn2 in"(选择regexp_substr(s.testval5,[^,] +,1,level )通过regexp_substr(s.testval5,[^,] +,1,level)的双连接不为空"

如果信息对您有用,则您可以接受答案并支持:)

一种快速的方法是在脚本开始时从表中收集所有可用的testval3和testval5组合,将它们存储在哈希表或类似的结构中,以便在读取每一行时都可以轻松地查询本地内存数据结构。

当然,它将使用更多的内存,但是它将运行单个验证查询并多次加速程序。

要运行的查询为select distinct mycolumn,mycolumn2 from mytable或等效查询。

看到

如何(或可以)在多列上选择DISTINCT?和

ORACLE Select Distinct返回许多列,其中

因此,总而言之,我提出的机制是:

运行查询以从表中选择所有不同的testval3和testval5对

创建一个哈希表和存储在其上的特定对结构。例如,在Java中,您可以使用Java值对集合? (元组?),然后,如果列的类型是字符串,则使用类似

HashMap, boolean> pairMap

确保实现hashCode和equals方法,就像在其他示例答案中一样,这样您就可以正确地将其用作地图上的键(如果使用Java或类似方法)

将查询结果存储在哈希表中,将testval3和testval5对作为表上的键,将true作为值(对结果集进行迭代的方法留给读者练习):

pairMap.put(new Pair(testval3,testval5),true)

逐行读取文件

在Foreach行中,查找哈希表上是否存在一对testval3和testval5,如果不存在则将其输出到CSV。为此,您只需查询地图并检查是否为空(HashMap中的键存在检查)

例如:

if (pairMap.get(new Pair(testval3,testval5)) == null) {

//output to CSV

}

最后,@ Kaushik Nayak所说的@Vivek暗示着另一种选择是,使用其数据加载工具将文件加载到Oracle上,然后对不存在的值运行单个查询。

谢谢你的建议。如果第一种方法行不通,将尝试此操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值