2016-11-02 8 views
1

私はこの質問に対する答えを知っていると思うが、ここでも専門家と確認したい。私は答えが「はい、バッチサイズの制限が16であり、これは少なすぎます。だから、事実上、バッチ処理はTeradata CLOBでは役に立たない」と述べています。TeradataのCLOBバッチ処理はJDBCでは役に立たないのですか?

ここに私の推論があります。ここに、動作中のJavaコードがあります。私は、Teradataのルールに基づいて

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(); 

をストリーミング使用して別の1つのデータベース接続からテーブルをコピーし、私は同時にオープンLOBに関連する16以上のオブジェクトを持つことができません。

したがって、Clob clobReader clobReaderがそれぞれ解放され、閉じられていることを確認する必要があります。

だから私は二つの選択肢

1を持っているが)executeBatch()法を行い、一度に最大16個のClob clobReader clobReaderオブジェクトを持っています。

2)​​メソッドを実行し、その直後に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オブジェクトをオープンする必要があります。一方、Teradataは、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を閉じることができるいくつかの "バッファ"(メモリ内または一時ファイル内)を見つけることです。その後、16の制限がないバッファからデータをバッチ挿入することができます(まだメモリの制限があります)。

+0

ありがとうございます。これは素晴らしいです – john

関連する問題