2016-11-02 2 views
1

나는이 질문에 대한 답을 알고 있다고 생각하지만, 전문가들과 함께이 질문을 확인하고 싶다. "그렇습니다. 배치 크기 제한이 너무 작기 때문에 16입니다. 따라서 실제적으로 일괄 처리는 테라 데이타 CLOB에서는 쓸모가 없습니다."Teradata CLOB 일괄 처리가 JDBC에서 쓸모 없습니까?

여기 내 이유가 있습니다. 다음은 작업중인 Java 코드입니다. 나는

public class TestClob { 

public void test() throws ClassNotFoundException, SQLException, IOException { 

Connection conn1, conn2; 
conn1 = DriverManager.getConnection(..., user, pass); 
conn2 = DriverManager.getConnection(..., user, pass); 

Statement select = conn1.createStatement(); 
ResultSet rs = select.executeQuery("SELECT TOP 100 myClob FROM myTab "); 

int totalRowNumber = 0; 

PreparedStatement ps = null; 
Clob clob = null; 
Reader clobReader = null; 

while (rs.next()) { 
totalRowNumber++; 
System.out.println(totalRowNumber); 
clob = rs.getClob(1); 
clobReader = clob.getCharacterStream(); 
ps = conn2.prepareStatement("INSERT INTO myTab2 (myClob2) values (?) "); 
ps.setCharacterStream(1, clobReader , clob.length()); 
ps.execute(); // HERE I just execute the current row 
clob.free(); // FREE the CLOB and READER objects 
clobReader.close(); 
} 

conn2.commit(); 
ps.close(); 
select.close(); 
rs.close(); 

은 테라 데이타의 규칙에 따라, 나는 동시에 열 LOB에 관련된 16 개 이상의 개체를 가질 수 없습니다 스트리밍을 사용하여 다른 하나 개의 데이터베이스 연결에서 테이블을 복사합니다.

따라서 Clob clobReader clobReader이 각각 해제되고 닫혀 있는지 확인해야합니다.

그래서 나는 두 가지 옵션

1

)을 executeBatch() 방법을 한 번에 16 Clob clobReader clobReader 개의 물체를 가지고 있습니다.

2) execute() 메서드를 수행하고 바로 뒤에 Clob clobReader clobReader 개체를 닫습니다.

결론 : Teradata CLOB 배치 삽입은 JDBC에서는 쓸모가 없습니다. 하나는

이 제발 도와주세요의 Clob를 삽입하려고 할 때 16 개 이상의의 배치 크기를 설정하고 나는이 제대로

내가 어떤 다른 방법이 표시되지 않는 이해하는 경우 알려 수 없습니다

+0

귀하의 사용 사례에서 제한 사항이 실제로 실망 스럽다는 것을 알고 있습니다. 그러나 이것이 CLOB 일괄 처리의 한계입니까? 파일에서 CLOB를 삽입하는 경우이 제한이 있습니까? – Insac

+0

파일에서 읽을'Reader' 개체가 있어야합니다. 그리고 Teradata LOB 규칙은 모든 객체가'executeUpdate'에 열려 있어야한다고 말하기 때문에 닫을 수 없습니다 https://developer.teradata.com/blog/tomnolan/2016/03/lob-locator-lifetime – john

+0

읽는 방법을 모르겠습니다. 파일에서 그것을 해결할 수 있습니다. 다른 데이터베이스 연결에서 직접 읽습니다. Teradata LOB 문제입니다. INSERT Teradata를 작성하려면 모든 LOB 오브젝트가 열려 있어야합니다. 반면 테라 데이타는 16 개가 넘지 않아야한다고 말합니다. – john

답변

1

당신 여기에 16 개 이상의 Clob을 일괄 삽입 한 예가 첨부되어 있습니다.

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.Reader; 
import java.io.StringReader; 
import java.security.GeneralSecurityException; 
import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.sql.Statement; 
import java.util.ArrayList; 
import java.util.List; 


public class ClobBatch { 

    public static void main(String[] args) throws GeneralSecurityException, IOException, SQLException { 

     String databaseCredentials = ExternalData.getCredentials(); 
     Connection c1=DriverManager.getConnection(databaseCredentials); 
     Connection c2=DriverManager.getConnection(databaseCredentials); 

     String sql="create volatile table clob_test_input (id bigint, longobj clob) no primary index on commit preserve rows;"; 
     Statement s=c1.createStatement(); 
     s.execute(sql); 

     String sql2="create volatile table clob_test_target (id bigint, longobj clob) no primary index on commit preserve rows;"; 
     Statement s2=c2.createStatement(); 
     s2.execute(sql2); 

     System.out.println("Inserting test data"); 
     PreparedStatement ps=c1.prepareStatement("insert into clob_test_input (id, longobj) values (?,?);"); 
     for(int i=0; i<1000; i++) { 
      String st=randomLargeString(); 
      ps.setInt(1, i); 
      ps.setCharacterStream(2, new BufferedReader(new StringReader(st)), st.length()); 
      ps.addBatch(); 
     } 
     ps.executeBatch(); 

     System.out.println("reading test data from input table"); 
     Statement select=c1.createStatement(); 
     ResultSet rs=select.executeQuery("select * from clob_test_input"); 


     PreparedStatement ps2=c2.prepareStatement("insert into clob_test_target (id, longobj) values (?,?);"); 
     List<Reader> readerToClose=new ArrayList<Reader>(); 
     System.out.println("start batch creation"); 
     while(rs.next()) { 
      int pos=rs.getInt("id"); 
      Reader rdr=new BufferedReader(rs.getCharacterStream("longobj")); 

      StringBuffer buffer=new StringBuffer(); 
      int c=0; 
      while((c=rdr.read())!=-1) { 
       buffer.append((char)c); 
      } 
      rdr.close(); 
      ps2.setInt(1, pos); 
      Reader strReader= new StringReader(buffer.toString()); 
      ps2.setCharacterStream(2, strReader,buffer.length()); 
      readerToClose.add(strReader); 
      ps2.addBatch(); 
     } 
     System.out.println("start batch execution"); 
     ps2.executeBatch(); 
     rs.close(); 
     c1.commit(); 
     c2.commit(); 

     for(Reader r:readerToClose) r.close(); 

     Statement selectTest=c2.createStatement(); 
     ResultSet rsTest=selectTest.executeQuery("select * from clob_test_target"); 
     System.out.println("show results"); 
     int i=0; 
     while(rsTest.next()) { 
      BufferedReader is=new BufferedReader(rsTest.getCharacterStream("longobj")); 
      StringBuilder sb=new StringBuilder(); 
      int c=0; 
      while((c=is.read())!=-1) { 
       sb.append((char)c); 
      } 
      is.close(); 
      System.out.println(""+rsTest.getInt("id")+' '+sb.toString().substring(0,80)); 
     } 

     rsTest.close(); 
    } 


    private static String randomLargeString() { 
     StringBuilder sb=new StringBuilder(); 
     for(int i=0;i<10000; i++) { 
      sb.append((char) (64+Math.random()*20)); 
     } 
     return sb.toString(); 
    } 
} 

좀 낙관적 인 가설 (예를 들어 10000 문자의 CLOB에)에 근무했지만 접근 방식 대신 StringBuffers의 임시 파일을 사용하여 집중적 메모리를 적게 할 수있다.

접근 방식은 기본적으로 소스 데이터베이스에서 데이터를 유지할 수있는 "버퍼"(메모리 또는 임시 파일에 있음)를 찾아 입력 ClobReader를 닫을 수 있도록합니다. 그런 다음 제한 사항이없는 버퍼에서 데이터를 일괄 적으로 삽입 할 수 있습니다 (여전히 메모리 제한이 있음).

+0

감사합니다. 이것은 훌륭하다. – john

관련 문제