Java 检查Oracle DB中的大量记录。shellscript作业超时
我每天都在做一项自动化工作,根据oracle数据库检查文本文件中的记录。 我们每天都会收到来自外部团队的文本文件,其中包含大约100000条记录。文本文件将采用unix格式,其中6列由|符号分隔 例如, HDR 1 TRL 我需要检查我的oracle数据库表中是否存在testval3和testval5中的值。该表有大约1000万条记录。 我目前正在通过shellscript处理它。在shellscript中,我读取文本文件并在循环中遍历每一行。在循环中,我从每一行传递值,并对DB运行查询。如果数据库中不存在这些记录,我必须将它们输出到csv文件中。使用以下查询:Java 检查Oracle DB中的大量记录。shellscript作业超时,java,database,oracle,shell,Java,Database,Oracle,Shell,我每天都在做一项自动化工作,根据oracle数据库检查文本文件中的记录。 我们每天都会收到来自外部团队的文本文件,其中包含大约100000条记录。文本文件将采用unix格式,其中6列由|符号分隔 例如, HDR 1 TRL 我需要检查我的oracle数据库表中是否存在testval3和testval5中的值。该表有大约1000万条记录。 我目前正在通过shellscript处理它。在shellscript中,我读取文本文件并在循环中遍历每一行。在循环中,我从每一行传递值,并对DB运行查询。如果数
select ‘testval3’,’testval5’ from dual
where not exists (select primarykeycolumn
from mytable where mycolumn=testval3 and mycolumn2=testval5)
由于输入文件有100000个条目,我的循环将运行100000次查询,每次它都会检查包含1000万条记录的表。这使我的批处理作业运行了很多小时,我必须终止它。有没有更好的方法来处理这种情况?如果没有更好的方法通过shellscript实现这一点,我也可以使用java。实现这一点的快速方法是从脚本开头的表中收集所有可用的testval3和testval5组合,将它们存储在哈希表或类似结构中,因此,当您读取每一行时,您可以轻松地查询本地内存中的数据结构 当然,它将使用更多内存,但它将运行单个验证查询并将程序速度提高很多倍 要运行的查询将是
选择distinct mycolumn、mytable中的mycolumn2
或等效项
看
- 及
HashMap pairMap
确保实现hashCode和equals方法,就像它们在另一个示例答案中一样,这样您就可以正确地将其用作映射上的键(如果使用Java或类似工具)
pairMap.put(新对(testval3,testval5),true)
if (pairMap.get(new Pair<String,String>(testval3,testval5)) == null) {
//output to CSV
}
if(pairMap.get(新对(testval3,testval5))==null){
//输出到CSV
}
最后,@Kaushik Nayak和@Vivek在评论中暗示的另一种选择,就是使用Oracle的数据加载工具将文件加载到Oracle上,然后对不存在的值运行单个查询。下面是一个简单的解决方案,它可以确保不会出现超时,甚至不需要扫描数百万条记录10万次 一次性设置: 创建暂存临时表:
create table a_staging_table(
testvalue1 varchar2(255),
testvalue2 varchar2(255),
testval3 varchar2(255),
testval4 varchar2(255),
testval5 varchar2(255)
);
----循环过程
将“CSV/TEXT”数据加载到暂存表中:
某些文件\u 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
您的数据将加载到临时表中。现在,将staging表和您的\u原始\u表连接起来,以标识不存在的记录
第一种方式:
使用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;
您使用的是UTL_文件吗?您使用的是哪个版本的Oracle?似乎您选择了效率最低的方法。您是否听说过SQL*加载器、外部表等?我的建议是首先在数据库中创建一个包含2列的表,并使用SQL*Loader将文件加载到该表中。然后使用一个查询,就可以提取所有需要的内容。与加载程序不同,外部表和UTL_文件需要目录权限。KaushikNayak他非常清楚自己的方式效率低下,这就是为什么他首先要在这里提出一个问题。只需省略前两个短语,您就可以给出相同的值。@Busybee:我发布了一个答案,可能是您正在寻找的东西。@VinkoVrsalovic:您怎么知道是“他”。此外,我不知道这样的问题在java标记下是否很少见,但在Oracle下,SQL*Loader之类的东西是希望OP知道的基本东西。我们需要连接数据库一百万次的逻辑并没有给我留下深刻印象。所以,问题是,为什么要使用它。没有必要再次建议使用循环。OP可以将输出假脱机为csv。另外,
groupby
可以替换为distinct
@KaushikNayak:谢谢你指出,我已经用DISTINCTYou替换了group。但是,我主要关心的是循环
,这不是必需的。如果OP可以使用sqlloader,那么他们也可以使用shell脚本中的sqlplus命令行来简单地假脱机输出。@KKK,谢谢您的详细解释。很抱歉,我没有首先提到这一点,testval5值将是一些用逗号分隔的值。例如,home/sample/file | testvalue1 | testvalue2 | testval3 | testval4 | test1,test2例如,home/sample/file | testvalue1 | testvalue2 | testvalue3 | testval4 | test1,test2,test3。test1、test2、test3的值是varchar2,我需要对照您在查询中提到的'mycolumn2'检查它们。原始_表中的mycolumn2始终具有单个值,如test1或test
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;