2012-03-08 6 views
0

내 논문의 기계 번역을 향상시키는 데 도움이되는 응용 프로그램을 작성하고 있습니다. 이를 위해서는 막대한 양의 ngram 데이터가 필요합니다. Google에서 데이터를 가져 왔지만 유용한 형식이 아닙니다.Java에서 대용량 데이터 파일 읽기 최적화

여기에 구글의 데이터를 포맷하는 방법은 다음과 같습니다

여기
ngram TAB year TAB match_count TAB page_count TAB volume_count NEWLINE 

이야 후 난 무엇을 :

ngram total_match_count_for_all_years 

그래서, 내가 파일을 실행하고 꺼내 작은 응용 프로그램을 작성한 총 수를 얻기 위해 여러 해 동안 데이터를 집계합니다. 그것은 그렇게 보인다. 그러나 Google 파일은 너무 크기 때문에 (1.5GB로, 그 중 99 개가> <) 모두 처리하는 데 오랜 시간이 걸립니다. 사람이 어떻게 이러한 파일의 처리 속도를 개선하는 아이디어가있는 경우

public class mergeData 
{ 
    private static List<String> storedNgrams = new ArrayList<String>(100001); 
    private static List<String> storedParts  = new ArrayList<String>(100001); 
    private static List<String> toWritePairs = new ArrayList<String>(100001); 
    private static int   rows   = 0; 
    private static int   totalFreq  = 0; 

    public static void main(String[] args) throws Exception 
     { 
      File bigram = new File("data01"); 
      BufferedReader in = new BufferedReader(new FileReader(bigram)); 
      File myFile = new File("newData.txt"); 
      Writer out = new BufferedWriter(new FileWriter(myFile)); 
      while (true)  
       { 
        rows = 0; 
        merge(in, out); 
       } 
     } 

    public static void merge(BufferedReader in, Writer out) throws IOException 
     { 

      while (rows != 1000000) 
       { 
        storedNgrams.add(in.readLine()); 
        rows++; 
       } 

      while (!(storedNgrams.isEmpty())) 
       { 

        storedParts.addAll(new ArrayList<String>(Arrays.asList(storedNgrams.get(0).split("\\s")))); 

        storedNgrams.remove(0); 

       } 
      while (storedParts.size() >= 8) 
       { 
        System.out.println(storedParts.get(0) + " " + storedParts.get(1) + " " + storedParts.get(6) 
          + " " + storedParts.get(7)); 
        if (toWritePairs.size() == 0 && storedParts.get(0).equals(storedParts.get(6)) 
          && storedParts.get(1).equals(storedParts.get(7))) 
         { 

          totalFreq = Integer.parseInt(storedParts.get(3)) + Integer.parseInt(storedParts.get(9)); 

          toWritePairs.add(storedParts.get(0)); 
          toWritePairs.add(storedParts.get(1)); 

          toWritePairs.add(Integer.toString(totalFreq)); 
          storedParts.subList(0, 11).clear(); 

         } 
        else if (!(toWritePairs.isEmpty()) && storedParts.get(0).equals(toWritePairs.get(0)) 
          && storedParts.get(1).equals(toWritePairs.get(1))) 
         { 

          int totalFreq = Integer.parseInt(storedParts.get(3)) 
            + Integer.parseInt(toWritePairs.get(2)); 

          toWritePairs.remove(2); 
          toWritePairs.add(Integer.toString(totalFreq)); 
          storedParts.subList(0, 5).clear(); 
         } 
        else if ((!toWritePairs.isEmpty()) 
          && !(storedParts.get(0).equals(storedParts.get(6)) && storedParts.get(1).equals(
            storedParts.get(7)))) 
         { 
          toWritePairs.add(storedParts.get(0)); 
          toWritePairs.add(storedParts.get(1)); 
          toWritePairs.add(storedParts.get(2)); 
          storedParts.subList(0, 2).clear(); 
         } 

        else if (!(toWritePairs.isEmpty())) 
         { 
          out.append(toWritePairs.get(0) + " " + toWritePairs.get(1) + " " + toWritePairs.get(2) 
            + "\n"); 
          toWritePairs.subList(0, 2).clear(); 

         } 

        out.flush(); 
       } 
     } 

} 

, 그것은 대단히 나에게 도움이 될 :

여기에 코드입니다.

+1

한 번에 두 줄 이상을 읽고 처리하는 이유는 무엇입니까? 당신은 당신이 필요로하는 것보다 약 5 배 더 많은 일을하고 있습니다. –

+0

고마워요, 고마워요, 고마워요! : D 어떤 이유로 한 번에 한 줄씩하는 것이 나에게 발생하지 않았습니다. 이제 모든 행을 제거하고 한 번에 한 행씩 처리 했으므로 속도가 매우 빠릅니다. –

답변

1

대용량 데이터를 읽고 나중에 처리하는 대신 이동하면서 데이터를 처리하는 것이 좋습니다. 프로그램에서 추출/집계하려고하는 정보가 명확하지 않습니다.

빠른 컴퓨터에서도 파일 당 약 20 초가 걸릴 것으로 예상됩니다.

2

데이터베이스에 임시 테이블을 만듭니다. 파일의 행으로 채 웁니다. 필요한 경우 색인을 작성하고 데이터베이스에서 그룹화하도록하십시오. 프로그램의 논리를 간소화하고 더 빨리 실행할 수 있습니다.

+0

파일 당 6,600 만 줄의 레코드를 사용하면 테이블에 모든 레코드를 넣을 때 시간이 오래 걸릴뿐 아니라 테이블이 커질 수 있습니다. –

+1

데이터베이스 용 팁을 사용하면 거대한 데이터를 삽입하기 전에 인덱스를 만들면 안됩니다. 행을 삽입 할 때마다 dbms가 다시 색인을 생성하기 때문에 행 번호에 시간이 걸립니다. –