2012-04-05 3 views
0

매우 큰 CSV 파일 인 ~ 800,000 행이 있습니다. 이 스크립트를 빠르게 처리하기 위해이 파일을 parellel에서 처리하려고합니다.루비를 사용하여 CSV 파일을 병렬 처리합니다.

루비를 사용하여 파일을 n 개의 작은 조각으로 나누는 방법은 무엇입니까?

+0

처리 비용이 많이 드는 부분은 무엇입니까? 대부분 CSV 자체를 구문 분석합니까, 아니면 후속 계산입니까? 계산이 실제로 병렬 처리가 가능합니까 아니면 이전 입력에 의존합니까? 레코드 구분 기호를 쉽게 식별 할 수 있습니까 (예 : 각 레코드가 "\ n"으로 끝나거나 필드에 "\ n"포함될 수 있습니까?)? – dbenhur

답변

2

청크로 CSV 파일을 분할하는 순서이지만 각 청크가 첫 번째 줄을 CSV 헤더로 유지해야한다는 점을 명심해야합니다!

그래서 UNIX 'split'은 그것을 자르지 않습니다!

첫 번째 줄을 읽은 다음 변수에 저장 한 후 다음 N 줄을 새로운 부분 CSV 파일로 배포하지만 처음에는 CSV- 줄 줄을 복사하는 작은 루비 스크립트를 작성해야합니다 .

헤더와 줄 청크가있는 각 파일을 만든 후에는 Resque를 사용하여 Resque 작업자가 병렬 처리 할 파일을 등록 할 수 있습니다.

http://railscasts.com/episodes/271-resque

0

linux split 명령을 사용하여이 파일을 여러 개의 작은 파일로 분할 할 수 있습니다. 그런 다음이 작은 부분들을 처리 할 것입니다.

+1

병목 현상이 디스크입니다. 파일을 별도의 디스크에 저장하지 않는 한 작은 파일로 분리하면 도움이되지 않습니다. – pguardiario

+0

사실 일 수 있지만 디스크 액세스를 피하는 방법. 다중 쓰레드라도, 각 쓰레드에 대한 파일 핸들이나 파일 핸들 위치가 스레드가 어떤 작업을 원할 때마다 이동되어야한다. 별도의 파일과 별도의 프로세스 (또는 스레드)를 사용하면 I/O 관련 스레드 일시 중단으로 인해 대기 시간을 최소화 할 수 있습니다. 내가 잘못? – tartar

+2

분할 프로세스 라인이지만 CSV는 인용 된 필드에 개 글자를 포함 할 수 있으므로 일반적으로 개행 전용으로 분할하는 것은 비현실적입니다. – dbenhur

2

CSV 파일의 경우이 작업을 수행 할 수 있습니다 배열 (메모리) 또는 파일에 저장 선 (또는 스플릿 라인)으로

open("your_file.csv").each_line do |line| 
    # do your stuff here like split lines 
    line.split(",") 

    # or store them in an array 
    some_array << line 

    # or write them back to a file 
    some_file_handler << line 
end 

, 당신은 작은 조각으로 큰 파일을 깰 수 있습니다. 그 후에 스레드를 사용하여 각 조각을 처리 할 수 ​​있습니다.

threads = [] 
1.upto(5) { |i| threads << Thread.new { do your stuff with file[i] } } 

threads.each(&:join) 

스레드 안전을 유지하는 것은 사용자의 책임입니다.

희망이 도움이됩니다.

갱신 :

pguardiario의 조언에 따르면, 우리는 스탠드 라이브러리에서 대신 직접 파일을 여는 CSV를 사용할 수 있습니다.

+2

이것은 csv 파일을 처리하는 잘못된 방법입니다. 대신 CSV 라이브러리를 사용하십시오. – pguardiario

+1

예, 우리는 csv lib를 사용해야합니다. 하지만 혜택은? – Tomato

+1

대부분의 경우 따옴표 붙이기와 헤더가 있지만 자세한 내용은 문서를 참조하십시오. 또한 당신이 옳은 방법을 할 때 당신이 얻는 좋은 느낌 :) – pguardiario

관련 문제