Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 检查Oracle DB中的大量记录。shellscript作业超时_Java_Database_Oracle_Shell - Fatal编程技术网

Java 检查Oracle DB中的大量记录。shellscript作业超时

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运行查询。如果数

我每天都在做一项自动化工作,根据oracle数据库检查文本文件中的记录。 我们每天都会收到来自外部团队的文本文件,其中包含大约100000条记录。文本文件将采用unix格式,其中6列由|符号分隔

例如, HDR 1

TRL

我需要检查我的oracle数据库表中是否存在testval3和testval5中的值。该表有大约1000万条记录。 我目前正在通过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。

实现这一点的快速方法是从脚本开头的表中收集所有可用的testval3和testval5组合,将它们存储在哈希表或类似结构中,因此,当您读取每一行时,您可以轻松地查询本地内存中的数据结构

当然,它将使用更多内存,但它将运行单个验证查询并将程序速度提高很多倍

要运行的查询将是
选择distinct mycolumn、mytable中的mycolumn2
或等效项

总之,我提议的机制是:

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

  • 创建一个哈希表和存储在上面的特定对结构。例如,在Java中,您可以使用,然后,如果列的类型是字符串,则使用

  • HashMap pairMap

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

  • 将查询结果存储在哈希表中,将testval3和testval5对作为表上的键,将true作为值(如何迭代resultset留给读者作为练习):
  • pairMap.put(新对(testval3,testval5),true)

  • 逐行读取文件
  • 对于每一行,查找哈希表上是否存在testval3和testval5对,如果不存在,则将该行输出到CSV。为此,您只需查询地图并检查null()
  • 例如:

     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;