Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/385.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的大容量插入_Java_Sql_Oracle_Performance_Bulk Operations - Fatal编程技术网

从Java到Oracle的大容量插入

从Java到Oracle的大容量插入,java,sql,oracle,performance,bulk-operations,Java,Sql,Oracle,Performance,Bulk Operations,我需要在Oracle中快速插入许多小行。(5个字段) 使用MySQL,我将插入分为100组,然后对每组100个插入使用一条insert语句 但对于Oracle,用户反馈说,大规模插入(从1000到30000)速度太慢 有没有类似的技巧可以用来加速从Java到Oracle的编程插入?现在MySQL是Oracle,所以也许一个更简单的解决方案是保留MySQL 如果没有,则应确保在启动插入组之前启动事务,一旦插入组完成,则提交事务并为下一组插入启动新事务 还要检查可能会减慢插入时间的不必要的索引定义

我需要在Oracle中快速插入许多小行。(5个字段)

使用MySQL,我将插入分为100组,然后对每组100个插入使用一条insert语句

但对于Oracle,用户反馈说,大规模插入(从1000到30000)速度太慢


有没有类似的技巧可以用来加速从Java到Oracle的编程插入?

现在MySQL是Oracle,所以也许一个更简单的解决方案是保留MySQL

如果没有,则应确保在启动插入组之前启动事务,一旦插入组完成,则提交事务并为下一组插入启动新事务

还要检查可能会减慢插入时间的不必要的索引定义

更新…
批量插入指的是(提取转换加载)的最后一步,因此您是否考虑过使用基于java的ETL工具,如或

Pentaho介绍了他们的Oracle批量装载设备


快速的谷歌搜索还显示了一些初步证据,表明Talend还支持Oracle批量加载。

您没有说明如何将这些记录传递到数据库。最好的方法是使用数组,因为这允许在所有批量操作中使用Oracle的大量功能

这个示例包有两个过程。一个用于填充T23记录的集合(一个包含五个数字列的表),另一个用于使用数组将记录批量插入该表

SQL> create or replace package p23 as
  2      type t23_nt is table of t23%rowtype;
  3      function pop_array ( p_no in number )
  4          return t23_nt;
  5      procedure ins_table ( p_array in t23_nt );
  6  end p23;
  7  /

Package created.

SQL> create or replace package body p23 as
  2
  3      function pop_array ( p_no in number )
  4          return t23_nt
  5      is
  6          return_value t23_nt;
  7      begin
  8          select level,level,level,level,level
  9          bulk collect into return_value
 10          from dual
 11          connect by level <= p_no;
 12          return return_value;
 13      end pop_array;
 14
 15      procedure ins_table
 16              ( p_array in t23_nt )
 17      is
 18          s_time pls_integer;
 19      begin
 20
 21          s_time := dbms_utility.get_time;
 22
 23          forall r in p_array.first()..p_array.last()
 24              insert into t23
 25              values p_array(r);
 26
 27          dbms_output.put_line('loaded '
 28                  ||to_char(p_array.count())||' recs in '
 29                  ||to_char(dbms_utility.get_time - s_time)
 30                  ||' csecs');
 31      end ins_table;
 32  end p23;
 33  /

Package body created.

SQL>

我认为在0.15秒内插入100000条记录应该会让所有人都满意,但要求最高的用户除外。所以,问题是,如何进行插入?

您可以使用Spring的DAO模块批量插入许多行

在一次更新中将订单对象集合插入数据库的示例:

public class OrderRepositoryImpl extends SimpleJdbcDaoSupport implements
        OrderRepository {

    private final String saveSql = "INSERT INTO orders(userid, username, coffee, coffeename, amount) "
            + "VALUES(?, ?, ?, ?, ?)";

    public void saveOrders(final Collection<Order> orders) {
        List<Object[]> ordersArgumentList = new ArrayList<Object[]>(orders
                .size());

        Object[] orderArguments;
        for (Order order : orders) {
            orderArguments = new Object[] { order.getUserId(),
                    order.getUserName(), order.getCoffe(),
                    order.getCoffeeName(), order.getAmount() };

            ordersArgumentList.add(orderArguments);
        }

        getSimpleJdbcTemplate().batchUpdate(saveSql, ordersArgumentList);
    }
}
公共类OrderRepositoryImpl扩展了SimpleJDBCDAO支持实现 订单存储库{ private final String saveSql=“插入订单(userid、用户名、咖啡、咖啡名、金额)” +“值(?,?,?,?)”; 公共作废保存单(最终收款单){ List ordersArgumentList=新建ArrayList(订单 .size()); 对象[]orderArguments; 对于(订单:订单){ orderArguments=新对象[]{order.getUserId(), order.getUserName(),order.getCoffe(), order.getCoffeeName(),order.getAmount()}; 添加(OrderArgumentList); } getSimpleJdbcTemplate(); } } 试试看

public Boolean inserTable(String fileName) {
    logger.info("Begin - " + this.getClass().getSimpleName() + "." + "inserTable");
        logger.info("File : " + fileName);
    try (Connection conn1 =  jdbcTemplate.getDataSource().getConnection();) {
        OracleConnection conn = ( OracleConnection ) conn1.getMetaData().getConnection();
        ScriptRunner sr = new ScriptRunner(conn);
        StringBuilder sBuffer = new StringBuilder();
        StringBuffer sb=new StringBuffer();
        String query = "Insert into TABLE_DATA (ID, DATA1, DATECREATED, CREATEDBY) Values ";
        String line = "";
        //Creating a reader object
        BufferedReader br = new BufferedReader(new FileReader(fileName),1024 * 1024 );
        while ((line = br.readLine()) != null) {
            //logger.info("Leyo linea : " + line);
            sb.append(query.concat("(").concat("TABLE_DATA_SQ.NEXTVAL,").concat(line.substring(0,6)).concat(",").concat("sysdate,").concat("'BDVENLINEA'").concat(");"));
            sb.append("\n");
        }
        sb.append("commit;");
        Reader reader = new StringReader(sb.toString());
        //Running the script
        sr.runScript(reader);
        reader.close();
        br.close();
        return true;
    } catch (FileNotFoundException e) {
        logger.error(e.getMessage(), e);
        throw new TechnicalException(e, e.getMessage());
    } catch (SQLException e) {
        e.printStackTrace();
        throw new TechnicalException(e, e.getMessage());
    } catch (IOException e) {
        e.printStackTrace();
        throw new TechnicalException(e, e.getMessage());
    } finally {
        logger.info("End   - " + this.getClass().getSimpleName() + "." + "inserTable");
    }
}

构建SQLPlus脚本,让Java/etc调用,而不是通过Java来完成。MySQL显然不是Oracle。公司是,但软件不是。此外,这是客户的选择。我更喜欢MySQL,但我们需要两者都支持。只是确认一下,它已经在一个事务中完成了。关于因为是Oracle而留在MySQL的评论被认为是一个笑话。。。有点。。。我又来了…谢谢。可能对某些人有用,但我正在上传基于web请求生成的动态计算数据。需要从Java完成。谢谢!对于来自java的jdbc,这是我唯一的限制。insert CLOB没有这么快though@yolob21:CLOB—数据量更大—从定义上讲几乎会更慢。那么你的观点是什么呢?我曾尝试使用java app(jdbc)将一个Oraclearray(每个元素都是一个特定于业务的对象的实例,其中包含一个clob和6个整数)传递到Oracle 12cr1中定义的一个过程中,通过forall将值从数组插入到表中,90%的clob值少于4000个字符,块大小为8k,但插入约100万行需要将近3分钟。与使用springJDBC提供的批处理大小为1000的BatchsqlUpdate相比,PointBeing数组方法并没有提供太多的速度差异,这之前需要4分钟。我这里不使用Spring,但要记住这一点。此解决方案的一个优点是,它在最后将所有数据作为一个大包发送。如果您正在为每一行执行更新,那么您也可以通过网络发送更新。JPA还提供与此Spring解决方案类似的批处理解决方案。
public Boolean inserTable(String fileName) {
    logger.info("Begin - " + this.getClass().getSimpleName() + "." + "inserTable");
        logger.info("File : " + fileName);
    try (Connection conn1 =  jdbcTemplate.getDataSource().getConnection();) {
        OracleConnection conn = ( OracleConnection ) conn1.getMetaData().getConnection();
        ScriptRunner sr = new ScriptRunner(conn);
        StringBuilder sBuffer = new StringBuilder();
        StringBuffer sb=new StringBuffer();
        String query = "Insert into TABLE_DATA (ID, DATA1, DATECREATED, CREATEDBY) Values ";
        String line = "";
        //Creating a reader object
        BufferedReader br = new BufferedReader(new FileReader(fileName),1024 * 1024 );
        while ((line = br.readLine()) != null) {
            //logger.info("Leyo linea : " + line);
            sb.append(query.concat("(").concat("TABLE_DATA_SQ.NEXTVAL,").concat(line.substring(0,6)).concat(",").concat("sysdate,").concat("'BDVENLINEA'").concat(");"));
            sb.append("\n");
        }
        sb.append("commit;");
        Reader reader = new StringReader(sb.toString());
        //Running the script
        sr.runScript(reader);
        reader.close();
        br.close();
        return true;
    } catch (FileNotFoundException e) {
        logger.error(e.getMessage(), e);
        throw new TechnicalException(e, e.getMessage());
    } catch (SQLException e) {
        e.printStackTrace();
        throw new TechnicalException(e, e.getMessage());
    } catch (IOException e) {
        e.printStackTrace();
        throw new TechnicalException(e, e.getMessage());
    } finally {
        logger.info("End   - " + this.getClass().getSimpleName() + "." + "inserTable");
    }
}