많은 양의 데이터에서 작동하는 정렬 알고리즘


12

대량의 데이터에서 작동 할 수있는 정렬 알고리즘을 찾고 있습니다. 즉, 전체 데이터 세트를 한 번에 주 메모리에 유지할 수없는 경우에도 작동 할 수 있습니다.

내가 지금까지 찾은 유일한 후보는 병합 정렬입니다. 메인 메모리의 모든 데이터를 한 번에 유지하지 않고 각 병합에서 데이터 세트를 스캔하는 방식으로 알고리즘을 구현할 수 있습니다. 필자가 생각한 병합 정렬의 변형은 이 문서의 테이프 드라이브 사용 섹션에 설명되어 있습니다 .

이것이 좋은 해결책이라고 생각합니다 (복잡성 O (nx log (n))) 그러나 주 메모리에 맞지 않는 큰 데이터 세트에서 작동 할 수있는 다른 (아마도 더 빠른) 정렬 알고리즘이 있는지 궁금합니다.

편집하다

답변에 필요한 자세한 내용은 다음과 같습니다.

  • 데이터는 주기적으로 (예 : 한 달에 한 번) 정렬해야합니다. 몇 개의 레코드를 삽입 할 필요가 없으며 데이터를 증분 정렬했습니다.
  • 내 예제 텍스트 파일은 약 1GB UTF-8 텍스트이지만 파일이 20GB 인 경우에도 일반적으로 문제를 해결하고 싶었습니다.
  • 데이터베이스에 없으며 다른 제한 조건으로 인해 사용할 수 없습니다.
  • 데이터는 다른 사람들이 텍스트 파일로 덤프합니다.이 텍스트 파일을 읽는 자체 코드가 있습니다.
  • 데이터 형식은 텍스트 파일입니다. 줄 바꾸기 문자는 레코드 구분 기호입니다.

내가 생각한 한 가지 개선 사항은 파일을 메모리에 정렬하기에 충분히 작은 파일로 분할하고 마지막으로 위에서 설명한 알고리즘을 사용하여 이러한 파일을 모두 병합하는 것이 었습니다.


1
어떤 종류의 데이터? 다른 데이터 세트는 목적에 가장 적합한 다른 알고리즘을 의미 할 수 있습니다.
whatsisname

텍스트 파일이며 줄을 정렬해야합니다. 줄 길이는 고정되어 있지 않지만 길이가 너무 다양하지는 않습니다 (레코드 당 약 50 자).
Giorgio

3
귀하의 환경이나 제약 조건을 모르지만 가능할 때마다 데이터베이스를 사용하여 정렬합니다. 이것은 거의 100 % 오류 방지 기능이며 내 코드보다 훨씬 효율적이기 때문입니다.
NoChance

Linux / Java에서 일하고 있습니다. 병합 정렬을 구현했으며 매우 원활하게 작동하는 것 같습니다. 수백만 줄을 정렬하는 데는 시간이 많이 걸리지 만 한 번만 수행하면됩니다.
Giorgio

@Giorgio, 그런 알고리즘을 구현 한 것이 좋습니다. 프로덕션 작업의 경우 여전히 데이터베이스를 사용하는 것이 좋습니다. 속도뿐만 아니라 신뢰성과 유지 보수 용이성을 위해.
NoChance

답변:


13

정렬 및 검색에 대한 표준 참조는 Knuth, Vol. 3 . 거기서 시작하십시오.

이 책은 원래 컴퓨터가 현재보다 훨씬 작고 느 렸을 때 다시 쓰여졌 기 때문에 메모리 부족 정렬 기술이 오늘날보다 훨씬 중요해졌습니다.


2
참조 주셔서 감사합니다 : 나는 Knuth의 책에서 흥미로운 자료를 찾을 것이라고 거의 확신합니다. 메모리 부족 정렬 기술이 오늘날 관련이 있는지 확실하지 않습니다. 일상적인 일상 업무는 아니지만 매우 큰 데이터 세트를 처리해야하는 상황이 여전히 많다고 생각할 수 있습니다.
Giorgio

Knuth의 알고리즘은 항상 도움이됩니다. 예를 들어 힙 정렬 버퍼와의 병합 정렬은 매우 효과적이고 구현하기 매우 쉽습니다.
Sulthan

4
참조 자료가 무료가 아니기 때문에 매우 유용한 답변은 아닙니다. OP의 경우 답변을 찾기 위해 인터넷 검색을 제안합니다. 이런 종류의 정보를 웹을 통해 찾아 볼 수있을 때 책을 얻기 위해 50 달러를 책정 할 필요가 없습니다. 물론, 당신은 아마 (에서 무료로이를 다운로드 할 수 있습니다 에헴 ) 특정 사이트뿐만 아니라. 받아 들여질만한 대답이 거의 없습니다.
Thomas Eding

1
@ThomasEding에는 "도서"라고하는 것들이 있는데,이 책에는 "도서"라고하는 오래된 정보 저장 장치와 검색 장치가 많이 들어 있습니다. "도서관"은 "도서"를 무료 대출로 제공합니다. 특정 "라이브러리"에 원하는 특정 "도서"가없는 경우, "라이브러리"가 다른 "라이브러리"에서 "도서"를 빌릴 수 있도록하는 "인터랙 터리 대출"이라는 무료 서비스도 제공합니다. 당신에게 빌려주십시오.
John R. Strohm

6

UNIX sort명령 에서와 같이 외부 R-Way 병합 이 좋은 대안입니다. 당신의 공식에서, 그것이 당신이 "병합 정렬 (merge sort)"에 의도 한 알고리즘인지 확실하지 않으며, 당신이 그것을 모른다면, 살펴보십시오.


감사. 외부 R-Way 병합은 내가 생각한 것과 다릅니다. 재미있는 독서.
Giorgio

4

더 구체적인 내용이 없으면 "병합 정렬"이 가장 적합한 답일 수 있지만 요구 사항에 따라 훨씬 더 똑똑한 것을 구현할 수 있습니다.

예를 들어 파일의 메모리 내 인덱스를 만든 다음 모든 키를 한 번에 복사하여 다양한 키 값의 위치를 ​​캐싱 할 수 있습니까? 1/2는 한 번에 메모리에 맞습니까, 아니면 1/1000000입니까? 두 번째 경우 메모리에 인덱스를 맞추지 못할 수 있습니다. 첫 번째 경우 두 개의 반쪽을보다 효율적으로 정렬 한 다음 마지막 단계에서 함께 병합 할 수 있습니다.

지옥, 당신이 그것을 지정하지 않았기 때문에 데이터가 모두 데이터베이스에있을 수 있습니다. 그렇다면 인덱스 테이블을 만들고 잘 호출 할 수 있습니다 (이것이 아니라고 추측하지만 그 사실을 지적합니다) 이와 같은 복잡한 문제를 해결하려면 상황이 중요합니다.)

한 번만 수행하고 매우 빠른 해킹을 찾고 있다면 유닉스를 실행하는 경우 외부 병합 정렬이 좋은 시작 인 것처럼 들립니다 (겉으로는 내장되어 있기 때문에)

순서대로 유지해야하고 항상 단일 레코드를 추가하는 경우 삽입 정렬이 필요합니다 (정렬 된 데이터에 단일 레코드를 추가하는 것은 항상 삽입 정렬입니다).

데이터를 "읽는"코드를 제어 할 수 있습니까? 그렇다면 디스크에서 데이터를 이동하여 정렬하는 대신 많은 형태의 인덱싱이 ALOT에 도움이 될 것입니다 (실제로 절대적인 요구 사항 임).

그래서:

  • 장소 또는 여러 파일?
  • 한 번, 주기적으로 또는 항상 정렬 상태로 유지합니까?
  • 메모리보다 얼마나 큰가? (전체 데이터 세트를 통과하는 메모리로드는 몇 개인가?)
  • 데이터베이스에 있습니까? 할 수 있습니까?
  • 데이터를 읽는 코드를 제어합니까, 아니면 다른 사람들이 파일을 직접 덤프합니까?
  • 파일 형식? (텍스트? 고정 레코드?)
  • 내가 묻지 않은 다른 특별한 상황이 있습니까?

답변 해주셔서 감사합니다. "In place or multiple record"는 무엇을 의미합니까?
Giorgio

죄송합니다. 답을 반드시 읽어야합니다. 여러 파일을 의미했습니다. 적절한 위치는 데이터베이스를 원하는 시점에서 고정 레코드 크기 및 색인 작성을 의미합니다.
Bill K

아니오 : 제자리에 없습니다 : 레코드의 크기가 고정되어 있지 않습니다. 현재 구현에 4 개의 임시 파일을 사용합니다.
Giorgio

출력을 코드로 해석 할 수 있습니까, 아니면 특정 형식 (플랫 텍스트 파일)이어야합니까? 무언가를 추가 할 때마다 또는 가끔씩 정렬해야하는 빈도는? 무언가가 추가되면 끝에 추가되거나 추가되는 코드를 작성할 수 있습니까?
Bill K

각 줄을 레코드로 파싱 할 수 있지만 (파일은 CSV 파일 임) 대부분의 필드는 텍스트입니다. 한 달에 한 번 (예 : 매월) 정렬해야하며 현재 구현으로 정렬하는 데 약 1 시간이 걸립니다. 줄을 삽입하려면 올바른 위치에 줄을 삽입하는 코드를 작성할 수 있습니다. 지금까지 작성한 코드를 사용하면 이러한 도구를 작성하는 데 20 분이 걸립니다.
Giorgio

3

확장 가능한 솔루션을 원한다면 map-reduce를 사용한 표준 정렬 구현 인 TeraSort를 살펴보십시오. StackOverflow에 대한 자세한 내용 .


1
+1 : 재미있는 링크. 병합 정렬이 map / reduce의 예가 아닌가? map은 하위 목록 정렬에 해당하고 reduce는 병합에 해당합니까?
Giorgio

그럴 수도 있지만 직접 작성하는 대신 Hadoop을 사용하여이 작업을 수행 할 수 있습니다.
m3th0dman

1

버킷 정렬에 관심이있을 수 있습니다 . 평균 사례 성능은 선형 시간입니다.

= O (n + d) n : 요소의 수, d = 데이터에 대한 직관이있는 경우 최대 숫자의 길이 '숫자'의 길이가 가장 큰 숫자를 알고 있다면 따라서 2 백만 개의 6 자리 숫자 => 0 (n)이 있으면 선형입니다.


0

외부 병합 정렬 알고리즘 (데이터가 연속 형인 경우) 또는 버킷 정렬계산 으로 계산 하는 버킷 정렬 (데이터가 불연속적이고 균일하게 분산 된 경우)을 사용하십시오.

아마도 가장 좋은 방법은 증분이 작은 경우 자신의 인덱스 / 매핑 파일을 작성하는 것입니다.

  1. 어떻게 든 "데이터베이스"를 주문하십시오
  2. 모든 항목에 정수를 할당하십시오 (1, 2, 3, 4, ..., n) (더 나은 : 희소 색인 사용)
  3. 증분을 추가 할 때 왼쪽 숫자가 작거나 같고 오른쪽 숫자가 크거나 같은 간격을 찾으십시오 (이진 검색의 일부 수정 버전에서는 어렵지 않아야 함)
  4. 삽입, 간격이 충분히 큰 반면, 그렇지 않다면 다시 색인화하십시오 (다시 정렬하지 마십시오 :-)

0

방금 메모리가 제한된 단일 시스템에서 빅 데이터 정렬 및 검색 작업을 단순화하기 위해 big queue 및 big array라는 추상 구조를 구축했습니다. 기본적으로 사용 된 알고리즘은 위에서 언급 한 알고리즘 (외부 병합 정렬)과 유사합니다.

단일 시스템에서 9 시간 안에 128GB 데이터 (각 항목 100 바이트)를 정렬 한 다음 거의 시간없이 정렬 된 데이터를 이진 검색 할 수 있습니다.

다음 은 오픈 소스 빅 큐 및 빅 어레이 구조를 사용하여 빅 데이터를 검색하는 방법에 대한 게시물입니다.

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