Windows에서 매우 큰 (800GB) 텍스트 파일의 내용 정렬


25

각 줄에 단어 가있는 텍스트 파일이 있으며 파일 크기는 800GB입니다. 알파벳순으로 단어를 정렬해야합니다.

다음을 사용하여 Windows 정렬 프로그램을 사용해 보았습니다 .

sort.exe input.txt /o output.txt

오류가 발생합니다 : 정렬을 완료하기에 주 메모리가 충분하지 않습니다.

32GB의 RAM이 있으므로 다음을 사용하여 정렬을 위해 10GB의 메모리를 지정하려고 할 때 :

sort.exe input.txt /o output.txt /M 10000000

나는 얻다:

경고 : 지정된 메모리 크기가 사용 가능한 페이징 메모리로 축소되었습니다.

입력 레코드가 최대 길이를 초과합니다. 더 큰 최대 값을 지정하십시오.

내 옵션은 무엇입니까?



10
이것은 교차 게시물이 아니며, 나는 기계가 아니므로 이것을 게시하고 다른 것을 삭제하는 데 몇 분이 걸립니다!
MaYaN

3
앞으로 지역 사회가 귀하의 질문을 이전하도록 허용
Ramhound

4
Linux에서는이 방법을 적용 할 수 있습니다 . 100Mb의 파일로 큰 문제는 아닙니다.
Eric Duminil

3
어떤 버전의 Windows를 사용하고 있습니까? 다소 오래된 Windows Server 2012 R2를 사용하는 sort.exe는 디스크에서 임시 파일을 사용하여 크기 제한을 문서화하지 않고 외부 병합 정렬을 수행 할 수 있다고 주장합니다. / T를 사용하여 임시 파일에 800Gb의 여유 디스크를 지정하십시오. "입력 레코드가 최대 길이를 초과합니다"라는 메시지는 공간과 관련이없는 것 같습니다. / REC 옵션을보고 줄 종결자가 무엇인지 고려하십시오.
davidbak

답변:


16

내 옵션은 무엇입니까?

프리웨어 명령 줄 정렬 유틸리티 CMSort을 사용해보십시오 .

여러 임시 파일을 사용한 다음 끝에 병합합니다.

CMsort는 조정 된 메모리에 도달 할 때까지 입력 파일의 레코드를 읽습니다. 그런 다음 레코드가 정렬되어 임시 파일에 기록됩니다. 모든 레코드가 처리 될 때까지이 과정이 반복됩니다. 마지막으로 모든 임시 파일이 출력 파일에 병합됩니다. 사용 가능한 메모리가 충분하면 임시 파일이 작성되지 않으며 병합이 필요하지 않습니다.

한 사용자가 130,000,000 바이트의 파일을 정렬했다고보고했습니다.

일부 코드를 직접 조정하려면 거대한 텍스트 파일 정렬-CodeProject- "텍스트 파일 크기의 사용 가능한 메모리를 초과하는 정렬 라인 알고리즘"도 있습니다.


26
와우 130 메가 바이트 !!! +1
David Foerster

3
@DavidPostill Windows 용 coreutils 에서 정렬하는 것이 더 효율적이지 않다고 확신 --parallel하십니까 (코어가 둘 이상인 경우 옵션 ...)?
Hastur

23

다른 옵션은 파일을 데이터베이스에로드하는 것입니다. EG MySQL 및 MySQL 워크 벤치.
데이터베이스는 대용량 파일 작업에 완벽한 후보입니다

입력 파일에 줄 바꿈으로 구분 된 단어 만 포함되어 있으면 힘들지 않아야합니다.

데이터베이스와 MySQL Workbench를 설치 한 후에는이 작업을 수행해야합니다.
먼저 스키마를 작성하십시오 (이는 인수 값을 늘려서이를 변경할 수는 있지만 단어가 255 자보다 길지 않다고 가정합니다). 첫 번째 열 "idwords"는 기본 키입니다.

CREATE SCHEMA `tmp` ;

CREATE TABLE `tmp`.`words` (
  `idwords` INT NOT NULL AUTO_INCREMENT,
  `mywords` VARCHAR(255) NULL,
  PRIMARY KEY (`idwords`));

두 번째로 데이터 가져 오기 : EG 모든 단어를 테이블로 가져옵니다 (이 단계를 완료하는 데 시간이 걸릴 수 있습니다. 작은 단어 파일로 먼저 테스트를 실행하고 형식이 동일한 지 확인하는 것이 좋습니다. 큰 것 (테이블 자르기. IE 그것을 지우고 전체 데이터 세트를로드하십시오).

LOAD DATA LOCAL INFILE "C:\\words.txt" INTO TABLE tmp.words
LINES TERMINATED BY '\r\n'
(mywords);


이 링크는로드에 적합한 형식을 얻는 데 도움이 될 수 있습니다. https://dev.mysql.com/doc/refman/5.7/en/load-data.html
EG 첫 번째 줄을 건너 뛰려면 다음을 수행하십시오.

LOAD DATA LOCAL INFILE "H:\\words.txt" INTO TABLE tmp.words
-- FIELDS TERMINATED BY ','
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES
(mywords);

마지막으로 정렬 된 파일을 저장하십시오. PC에 따라 시간이 걸릴 수도 있습니다.

SELECT tmp.words.mywords
FROM tmp.words
order by tmp.words.mywords asc
INTO OUTFILE 'C:\\sorted_words.csv';

원하는대로 원하는대로 데이터를 검색 할 수도 있습니다. EG 처음 50 개 단어를 오름차순으로 제공합니다 (0 번째 또는 첫 번째 단어부터 시작).

SELECT tmp.words.mywords
FROM tmp.words
order by tmp.words.mywords asc
LIMIT 0, 50 ;

행운을 빌어 요
피트


2
이것은 IS 상당한 차이로 정답.
MonkeyZeus

1
예를 들어 다른 순서로 정렬을 다시 실행해야하는 경우이 방법이 더욱 유연 해집니다.
바베큐

MySQL , MariaDB 또는 다른 DBMS 인스턴스가 얼마나 빠른지 상관하지 않습니다 . 동일한 컴퓨터에서 실행되는 SQLite 의 삽입 성능에 가까운 곳은 아닙니다 . 심지어 뭔가 빨리 SQLite는 최적의 솔루션 정렬 먼저 중복을 제거하는 것입니다 수 있도록 데이터의 양 (신뢰 제가 첫 번째 시도!) 너무 많은 (느린) 과정 인 다음에 삽입 DB 와 같은 SQLite는 . 따라서이 솔루션은 어떤 경우에는 유효 할 수 있지만 확실히 내가하려는 일이 아닙니다. 어쨌든 이것을 게시 할 시간을 내 주셔서 감사합니다.
MaYaN

로 주문하는 mywords데는 시간이 오래 걸립니다. 을 사용하더라도 LIMITMySQL은 모든 단일 값을 거치고 mywords순서 를 정해야하기 때문에 전체 시간이 소요 됩니다. 이 문제를 해결하려면 작업을 마친 후 다음을 수행해야합니다 LOAD DATA. 에 색인을 추가하십시오 mywords. 이제 해당 열을 기준으로 주문할 수 있으며 천년이 걸리지 않아도됩니다. 또한 테이블을 만들 때가 아니라 데이터를로드 한 후 인덱스를 추가하는 것이 좋습니다 (데이터로드가 훨씬 빠름).
Buttle Butkus

7

sort

정렬 된 파일과 정렬되지 않은 파일을 정렬하는 데 사용되는 많은 알고리즘이 있습니다 [ 1 ] .
모든 알고리즘이 이미 구현되었으므로 이미 테스트 된 프로그램을 선택하십시오.

에서 로 coreutils (리눅스에서하지만 창에 사용할 수도 [ 2 ] ), 그것은 존재 sort멀티 코어 프로세서에서 병렬로 실행할 수있는 명령을 : 보통은 충분하다.

파일이 너무 큰split -l 경우 병렬 옵션 ( --parallel)을 사용 하고 결과로 정렬 된 청크-m옵션 ( merge sort )으로 정렬 하여 처리 분할 ( ), 일부 청크에서 파일을 처리 할 수 ​​있습니다 . 여기
에는 여러 가지 방법 중 하나가 설명되어 있습니다 (파일 분리, 단일 청크 주문, 정렬 된 청크 병합, 임시 파일 삭제).

노트:

  • Windows 10에는 모든 Linux 예제가 더 자연스럽게 보이는 Linux 용 Windows 하위 시스템이 있습니다.
  • 다른 알고리즘으로 정렬하면 정렬 할 데이터 항목 수 (O (n m ), O (nlogn) ...)의 함수로 확장되는 실행 시간이 다릅니다 .
  • 알고리즘의 효율성은 원본 파일에 이미 존재하는 순서에 따라 다릅니다.
    예를 들어, 기포 정렬 은 이미 주문한 파일에 대해 가장 빠른 알고리즘 (정확히 N)이지만 다른 경우에는 효율적이지 않습니다.

2

Peter H에 대한 대체 솔루션을 제공하기 위해 텍스트 파일에 대해 SQL 스타일 명령을 허용 하는 프로그램 q 가 있습니다. 아래 명령은 SQL Workbench를 설치하거나 테이블을 만들 필요없이 파일과 동일한 디렉토리에서 명령 프롬프트에서 실행하는 것과 동일합니다.

q "select * from words.txt order by c1"

c1 1 열의 약어입니다.

중복 단어를 사용하여 제외 할 수 있습니다

q "select distinct c1 from words.txt order by c1"

출력을 다른 파일로 보냅니다

q "select distinct c1 from words.txt order by c1" > sorted.txt

이것이 800 기가 파일에 대처할 것인지 아는가?
롤링

1
100 % 확실하지 않습니다-위의 1200 줄 파일 (9KB)로 테스트했습니다. 개발자 페이지에는 최대 파일 크기에 대한 언급이없는 "제한"페이지가 있습니다. 메모리 문제로 인해 여전히 큰 파일이 나타날 수 있습니다.
Brian

3
q 이 양의 데이터를 처리 할 수 ​​없음 q 데이터를 SQLite로 직접로드 할 수없는 경우 q가 할 수 있다고 생각하는 q 가 장면 뒤에서 SQLite를 사용 한다는 것을 기억 하십니까?
MaYaN

2

각 줄의 단어가 영어와 같은 제한된 어휘에서 나온 경우 TreeMap 및 기록 횟수 (여기서 m은 고유 한 값의 개수)를 사용하여 O (n + m log m) 시간으로 목록을 정렬 할 수 있습니다.

그렇지 않으면 java 라이브러리 big-sorter를 사용할 수 있습니다 . 입력을 정렬 된 중간 파일로 분할하고 효율적으로 병합합니다 (전체 O (nlogn)). 파일을 정렬하는 방법은 다음과 같습니다.

Sorter.serializerTextUtf8()
      .input(inputFile)
      .output(outputFile)
      .loggerStdOut() // display some progress
      .sort();

무작위로 생성 된 16 문자 단어로 1.7GB 파일 (100m 줄)을 만들고 142 초에 위와 같이 정렬했으며 사용중인 방법의 O (n log n) 계산 복잡도에 따라 16 문자 단어의 800GB는 SSD가 장착 된 i5 2.3GHz 랩톱에서 단일 스레드를 정렬하는 데 약 24 시간이 걸립니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.