2014-10-06 2 views
1

배경 : Netbeans에서 Java로 작업하고 있습니다.java sqlite autocommit slow 느림

CSV 파일에서 행을 읽고 SQLite 데이터베이스에 삽입하고 있습니다. 내가 생각할 수있는 아주 기본적인 것들. 이 사이트 및 다른 곳에있는 예제에서 다음 코드를 생성했습니다. 그것은 작동하지만 얼마나 느린 지 알고 놀랐습니다. db에 46 줄을로드하는 데는 3.95 초가 걸립니다! Netbeans Profiler를 사용하면 3.7 초가 소요되는 autoCommit()을 볼 수 있습니다.

내가 뭘 잘못하고 있니? 아니면, MySQL 대신 SQLite를 사용하는 것에 대한 벌칙입니까?

 public static void LoadJCNAClassesTable(Connection aConn, String strPath) throws SQLException{ 
    String [] nextLine; 
    String strDivision; 
    String strClass; 
    String strNotes; 
    String strDescription; 

    Statement stat = aConn.createStatement(); 
    stat.executeUpdate("drop table if exists JCNAClasses;"); 
    String q = "create table JCNAClasses ('ID' INTEGER PRIMARY KEY AUTOINCREMENT, 'division' TEXT NOT NULL, 'class' TEXT NOT NULL UNIQUE, 'description' TEXT NOT NULL, 'note' TEXT NOT NULL, 'node' INTEGER NOT NULL);"; 
    stat.executeUpdate(q); 
    CSVReader reader; 
    int iLine; 

    String JCNAClassesCSV = strPath + "\\JCNAClassesCsv.txt" ; 

    try { 
     reader = new CSVReader(new FileReader(JCNAClassesCSV)); 
     iLine = 0; 
     while ((nextLine = reader.readNext()) != null) { 
      // nextLine[] is an array of values from the line 
     // System.out.println(nextLine[0] + nextLine[1]); 
      if (iLine > 0){ 
       strDivision = nextLine[0]; 
       strClass = nextLine[1]; 
       strDescription= nextLine[2]; 
       strNotes= nextLine[3]; 
       PreparedStatement prep = aConn.prepareStatement("insert into JCNAClasses ('division', 'class', 'description', 'note', 'node') values (?, ?, ?, ?, ?);"); 
       prep.setString(1, strDivision); // note that the comma seems not to be a problem 
       prep.setString(2,strClass); 
       prep.setString(3,strDescription); 
       prep.setString(4,strNotes); 
       prep.setInt(5,iLine); 
       prep.addBatch(); 
       aConn.setAutoCommit(false); 
       prep.executeBatch(); 
       aConn.setAutoCommit(true); 

      } 
      iLine++; 
     } 
    } catch (FileNotFoundException ex) { 
      Logger.getLogger(Entries.class.getName()).log(Level.SEVERE, null, ex); 
     }  
     catch (IOException ex) { 
      Logger.getLogger(Entries.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (SQLException ex) { 
      Logger.getLogger(LoadSQLiteConcoursDatabase.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 

    public static void LoadConcoursEntriesTable(Connection aConn, String strPath) throws SQLException{ 
String [] nextLine; 
String strEntryName; 
String strClass; 
Integer intYear; 
String strDescription; 
String strOwnerFirst; 
String strOwnerLast; 
Integer intJCNA; 
String strColor; 
String strPlate; 
Integer intNode; 
Long intPersonnel_id; 
Long intJaguar_id; 
ResultSet generatedKeys; 
String strStatus; 
int intPersonnelNode; 
ResultSet r; 

CSVReader reader; 
String q; 
int iLine; 
PreparedStatement prep; 
ResultSet rs; 
Statement stat = aConn.createStatement(); 
// 
// Concourse Personnel Table: Owners, Judges, & Interested parties 
// 
stat.executeUpdate("drop table if exists ConcoursPersonnel"); 
// status: Owner = "O"; "J" = Judge; "OJ" = Owner & Judge; "IP" = Interested party, e.g., spouse, restorer 
q = "create table ConcoursPersonnel ('personnel_id' INTEGER PRIMARY KEY AUTOINCREMENT , 'ownerfirst' TEXT NOT NULL, 'ownerlast' TEXT NOT NULL, 'jcna' INTEGER NOT NULL UNIQUE ON CONFLICT IGNORE, 'status' TEXT NOT NULL, 'node' INTEGER NOT NULL UNIQUE)"; 
stat.executeUpdate(q); 

// 
// Concours Jaguar Table 
// 
stat.executeUpdate("drop table if exists ConcoursJaguars"); 
q = "create table ConcoursJaguars ('jaguar_id' INTEGER PRIMARY KEY AUTOINCREMENT , 'class' TEXT NOT NULL, 'year' TEXT NOT NULL, 'description' TEXT NOT NULL, 'Color' TEXT, 'plate' TEXT, 'node' INTEGER NOT NULL UNIQUE)"; 
stat.executeUpdate(q); 

// 
// Entry Table (a Relationship or "link" between Personnel & Jaguars 
// 
stat.executeUpdate("drop table if exists ConcoursEntries"); 
q = "create table ConcoursEntries (entry_name TEXT NOT NULL, personnel_id INTEGER NOT NULL, jaguar_id INTEGER NOT NULL, UNIQUE (personnel_id, jaguar_id), FOREIGN KEY (personnel_id) REFERENCES ConcoursPersonnel (Personnel_ID), FOREIGN KEY (jaguar_id) REFERENCES ConcoursPersonnel (jaguar_id))"; 
stat.executeUpdate(q); 
String EntriesCSV = strPath + "\\EntriesCsv.txt" ; 
strStatus = "O"; // not in the CSV data so set to Owner 
try { 
    reader = new CSVReader(new FileReader(EntriesCSV)); 
    iLine = 0; 
    while ((nextLine = reader.readNext()) != null) { 
     // nextLine[] is an array of values from the line 
     // System.out.println(nextLine[0] + nextLine[1]); 
     if (iLine > 0){ 
      strEntryName = nextLine[0]; 
      strClass = nextLine[1]; 
      intYear= Integer.parseInt(nextLine[2]); 
      strDescription= nextLine[3]; 
      strOwnerFirst= nextLine[4]; 
      strOwnerLast= nextLine[5]; 
      intJCNA = Integer.parseInt(nextLine[6]) ; 
      strColor= nextLine[7]; 
      strPlate= nextLine[8]; 
      intNode= Integer.parseInt(nextLine[9]); // Since Jaguars are 1-to-1 with Entries this is used as Node number for both. However, it can't be used for Personnel Node 
      // 
      // Load Owners into Personnel Table 
      // 
      Statement s = aConn.createStatement(); 
      r = s.executeQuery("SELECT COUNT(*) AS rowcount FROM ConcoursPersonnel"); 
      r.next(); 
      intPersonnelNode = r.getInt("rowcount") +1 ; // Assignes Personnel node numbers as a continuous sequence 

      prep = aConn.prepareStatement("insert into ConcoursPersonnel ('ownerfirst', 'ownerlast', 'jcna', 'status', 'node') values (?, ?, ?, ?, ?);"); 
      //prep.setString(1, strEntryName); // note that the comma seems not to be a problem 
      prep.setString(1,strOwnerFirst); 
      prep.setString(2,strOwnerLast); 
      prep.setInt(3,intJCNA); 
      prep.setString(4,strStatus); 
      prep.setInt(5,intPersonnelNode); 
      prep.addBatch(); 
      aConn.setAutoCommit(false); // starts transaction 
      prep.executeBatch(); 
      aConn.setAutoCommit(true); // ends transaction 

      aConn.setAutoCommit(false); // starts transaction 
      stat = aConn.createStatement(); 
      generatedKeys = stat.executeQuery("SELECT last_insert_rowid()"); 
      intPersonnel_id = 0L; // won't be used 
      if (generatedKeys.next()) { 
       intPersonnel_id = generatedKeys.getLong(1); 
      } 
      else{ 
       System.out.println("No Personnel ID found in LoadConcoursEntriesTable"); 
       System.exit(-1); 
      } 
      aConn.setAutoCommit(true); // Commits transaction. 
      // 
      // Load Entry cars into the ConcoursJaguars table 
      // 
      prep = aConn.prepareStatement("insert into ConcoursJaguars ('class', 'year', 'description', 'color', 'plate', 'node') values (?, ?, ?, ?, ?, ?);"); 
      prep.setString(1,strClass); 
      prep.setInt(2,intYear); 
      prep.setString(3,strDescription); 
      prep.setString(4,strColor); 
      prep.setString(5,strPlate); 
      prep.setInt(6,intNode); //           
      prep.addBatch(); 
      aConn.setAutoCommit(false); 
      prep.executeBatch(); 
      aConn.setAutoCommit(true); 

      q = "select jaguar_id from ConcoursJaguars where node == " + intNode + ";"; 
      rs = stat.executeQuery(q); 
      intJaguar_id = rs.getLong("jaguar_id"); 

      prep = aConn.prepareStatement("insert into ConcoursEntries (entry_name, personnel_id, jaguar_id) values (?, ?, ?);"); 
      //prep.setString(1, strEntryName); // note that the comma seems not to be a problem 
      prep.setString(1,strEntryName); 
      prep.setLong(2,intPersonnel_id); 
      prep.setLong(3,intJaguar_id); 
      prep.addBatch(); 
      aConn.setAutoCommit(false); 
      prep.executeBatch(); 
      aConn.setAutoCommit(true); 
     } 
     iLine++; 
    } 
} catch (FileNotFoundException ex) { 
     Logger.getLogger(Entries.class.getName()).log(Level.SEVERE, null, ex); 
    }  
    catch (IOException ex) { 
     Logger.getLogger(Entries.class.getName()).log(Level.SEVERE, null, ex); 
    } catch (SQLException ex) { 
     Logger.getLogger(LoadSQLiteConcoursDatabase.class.getName()).log(Level.SEVERE, null, ex); 
    } 

}

답변

0

당신은 당신의 PreparedStatement를 재현하는 매번 당신은 당신의 루프를 통해 이동합니다. 이것은 while 루프 바로 전에 이동해야합니다.

또한 루프 외부에서 setAutoCommit 옵션을 한 번 설정해야합니다. 그런 다음 합리적인 한도를 맞추거나 완료 할 때 명령문을 커밋해야합니다.

당신은 여기에 게시 예를 볼 수 실제로 루프 내에서 커밋 실행한다됩니다 true로 자동 커밋 설정 Java: Insert multiple rows into MySQL with PreparedStatement

+0

이렇게하면 하나의 테이블을 만드는 문제가 해결되지만 관계가있는 다른 테이블이 있습니다. 특히, 나는 "Entries"(자동차 쇼에서와 같이)라고 부르는 CSV 파일을 가지고 있는데, 각 엔트리에는 Owner와 하나 이상의 Cars가 있습니다. 나는 Entries라고하는 링크 테이블과 함께 한 테이블에 Cars를, 다른 테이블에 Cars를 갖고 싶습니다. Entries.csv 파일 전체를 스윕하면서 단일 루프 내에서이 3 개의 테이블을 모두 만들고 있습니다. 이 상황에서 나는 owner 테이블과 car 테이블에서 executeBatch()를 건너 뛸 수 없다. 왜냐하면 만약 엔트리가 완료되지 않았다면 Entries 테이블에 삽입하기위한 외래 키를 가지고 있지 않기 때문이다. –

+0

CSV 파일의 형식 외에도 3 개의 테이블과 그 관계를 질문에 추가 할 수 있습니까? – lcersly

+0

Personnel 테이블, Juguars 테이블, Entries 링크 테이블을 생성하는 LoadConcoursEntriesTable() 코드를 추가했습니다. CVS 파일의 형식은 코드에서 분명하지만 원하는 경우 파일 자체를 제공 할 수 있습니다. 그것은 41 행입니다. –

0

합니다. 따라서 일괄 처리 작업은 실행되지 않습니다. 루프를 반복 할 때마다 커밋합니다. 일괄 작업을하려면 다음을 수행해야합니다

  1. prep.executeBatch(); (즉, aConn.setAutoCommit(false);aConn.setAutoCommit(true);)를 포장
  2. 제거 라인
  3. 이동 prep.executeBatch(); 루프
  4. 추가 라인에서 당신의 while 연산자 앞에 aConn.setAutoCommit(false);를 추가 aConn.commit(); while 루프가 끝난 직후

    aConn.setAutoCommit(false); 
    PreparedStatement prep = aConn.prepareStatement("insert into JCNAClasses ('division', 'class', 'description', 'note', 'node') values (?, ?, ?, ?, ?);"); 
    while ((nextLine = reader.readNext()) != null) { 
     if (iLine > 0){ 
     // some preparations go here 
     prep.addBatch(); 
     } 
     iLine++; 
    } 
    prep.executeBatch(); 
    aConn.commit();