폴더에있는 수백만 개의 작은 텍스트 파일


15

우리는 서비스로서 임의의 컬렉션을 압축하고 제공 할 수 있도록 Linux 파일 시스템에 수백만 개의 텍스트 파일을 저장하려고합니다. 키 / 값 데이터베이스와 같은 다른 솔루션을 시도했지만 동시성 및 병렬 처리 요구 사항에 따라 기본 파일 시스템을 사용하는 것이 가장 좋습니다.

가장 간단한 방법은 모든 파일을 폴더에 저장하는 것입니다.

$ ls text_files/
1.txt
2.txt
3.txt

이는 EXT4 파일 시스템 에서 가능해야하며 폴더의 파일 수에는 제한이 없습니다.

두 가지 FS 프로세스는 다음과 같습니다.

  1. 웹 스크랩에서 텍스트 파일을 작성합니다 (폴더의 파일 수에 영향을받지 않아야 함).
  2. 파일 이름 목록에 따라 선택된 파일을 압축합니다.

내 질문은 폴더에 최대 천만 개의 파일을 저장하면 위의 작업 또는 일반 시스템 성능에 영향을 미치므로 파일을 저장할 하위 폴더 트리를 만드는 것과 다른가?


4
관련 : 장치에 충분한 공간이있는 경우 MV 중 오류 "장치에 남아있는 공간"간헐적 해결하지하는 방법 . dir_index기본적으로 자주 사용되는을 사용하면 조회 속도가 빨라지지만 디렉토리 당 파일 수는 제한 될 수 있습니다.
Mark Plotnick

가상 머신에서 빠르게 시도해보고 어떤 모습인지 확인하십시오. bash를 사용하면 폴더 안에 임의의 문자가 포함 된 백만 개의 텍스트 파일이있는 폴더를 채울 수 있습니다. 여기서 배우는 것 외에도 실제로 유용한 정보를 얻을 수 있다고 생각합니다.
JoshuaD

2
@JoshuaD : 새로운 FS에 한 번에 모두 채우면 모든 inode가 디스크에 인접 해 ls -l있거나 stat디렉토리의 모든 inode (예 : 글 bash로빙 / 탭 완성)가 인위적으로 더 빠릅니다. 일부 마모 후보다 (일부 파일을 삭제하고, 새 파일을 작성하십시오). ext4는 XFS보다 이것을 사용하여 더 잘 할 수 있습니다 .XFS는 동적으로 inode에 대한 공간을 데이터에 할당하기 때문에 더 흩어져있는 inode로 끝날 수 있다고 생각합니다. (그러나 그것은 매우 작은 지식에 기초한 순수한 추측입니다; 나는 ext4를 거의 사용하지 않았습니다). abc/def/하위 디렉토리로 이동 하십시오.
Peter Cordes

그러나, 내가 제안한 테스트가 OP에 "이것은 작동 할 것"이라고 말할 수 있다고 생각하지 않지만, "이것은 작동하지 않을 것"이라고 확실히 말할 수 있는데, 이는 유용합니다.
JoshuaD

1
그러나 동시성 및 병렬 처리에 대한 우리의 요구 사항에 따라 기본 파일 시스템을 사용하는 것이 최선의 선택입니다 . 필자는 MySQL과 같은 저가형 RDBMS와 zip 파일을 즉시ZipOutputStream 생성하는 Java 서블릿조차도 무료 Linux 기본 파일 시스템을 능가 할 것이라고 생각한다. JDBC 결과 세트를 처리하고 zip 스트림을 작성하는 루프는 아마도 6-8 줄의 Java 코드 일 것입니다.
Andrew Henle

답변:


10

ls명령, 또는 TAB 완성 또는 쉘 와일드 카드 확장 보통 알파벳 순서로 결과를 제시한다. 전체 디렉토리 목록을 읽고 정렬해야합니다. 단일 디렉토리에 천만 개의 파일이 있으면이 정렬 작업은 무시할 수없는 시간이 걸립니다.

탭 완성의 욕구에 저항하고 압축 할 파일의 이름을 쓰면 아무런 문제가 없습니다.

와일드 카드의 또 다른 문제점은 와일드 카드 확장으로 최대 길이 명령 행에 맞는 것보다 많은 파일 이름을 생성 할 수 있습니다. 일반적인 최대 명령 줄 길이는 대부분의 상황에 적합하지만 단일 디렉토리에있는 수백만 개의 파일에 대해 이야기 할 때는 더 이상 안전한 가정이 아닙니다. 와일드 카드 확장에서 최대 명령 줄 길이를 초과하면 대부분의 셸은 전체 명령 줄을 실행하지 않고 실패합니다.

다음 find명령을 사용하여 와일드 카드 작업을 수행하면이 문제를 해결할 수 있습니다 .

find <directory> -name '<wildcard expression>' -exec <command> {} \+

또는 가능할 때마다 유사한 구문. 는 find ... -exec ... \+자동으로 계정에 최대 명령 줄 길이를 취할 것이며, 각 명령 줄에 파일 이름의 최대 양을 맞는 동안 필요한만큼 여러 번 명령을 실행합니다.


최신 파일 시스템은 B, B + 또는 유사한 트리를 사용하여 디렉토리 항목을 유지합니다. en.wikipedia.org/wiki/HTree
dimm

4
그렇습니다 ...하지만 쉘이나 ls명령이 디렉토리 목록이 이미 정렬되어 있음을 알지 못하면 정렬 알고리즘을 실행하는 데 시간이 걸립니다. 게다가, 사용자 공간은 파일 시스템이 내부적으로 할 수있는 것과 다른 현지화 된 정렬 순서 (LC_COLLATE)를 사용하고있을 수 있습니다.
telcoM

17

이것은 의견에 근거한 질문 / 답변과 밀접한 관련이 있지만 의견에 몇 가지 사실을 제공하려고 노력할 것입니다.

  1. 폴더에 매우 많은 수의 파일이있는 경우 파일을 열거하려는 셸 기반 작업 (예 mv * /somewhere/else:)이 와일드 카드를 성공적으로 확장하지 못하거나 결과가 너무 커서 사용할 수 없습니다.
  2. ls 적은 수의 파일보다 많은 수의 파일을 열거하는 데 시간이 더 걸립니다.
  3. 파일 시스템은 단일 디렉토리에서 수백만 개의 파일을 처리 할 수 ​​있지만 사람들은 아마 어려움을 겪을 것입니다.

한 가지 권장 사항은 파일 이름을 2, 3 또는 4 개의 문자 청크로 나누고 하위 디렉토리로 사용하는 것입니다. 예를 들어 somefilename.txt로 저장 될 수 있습니다 som/efi/somefilename.txt. 숫자 이름을 사용하는 경우 더 균일 한 분포가되도록 왼쪽에서 오른쪽 대신 왼쪽에서 오른쪽으로 분할하십시오. 예를 들어 12345.txt로 저장 될 수 있습니다 345/12/12345.txt.

zip -j zipfile.zip path1/file1 path2/file2 ...ZIP 파일에 중간 서브 디렉토리 경로를 포함하지 않도록하기 위해 동등한 것을 사용할 수 있습니다 .

웹 서버에서 이러한 파일을 제공하는 경우 (그것이 관련이 있는지 확실하지는 않습니다) Apache2에서 다시 쓰기 규칙이있는 가상 디렉토리를 선호 하여이 구조를 숨기는 것이 쉽지 않습니다. Nginx도 마찬가지입니다.


*당신이 메모리가 부족하지 않는 한 확장은 성공하지만 당신은 (리눅스) 스택 크기 제한을 늘리거나 쉘 사용하지 않는 mv내장 또는 (경우 ksh93, zsh을) 내장 할 수의 execve()시스템 호출은 E2BIG의 오류와 함께 실패 할 수 있습니다.
Stéphane Chazelas

@ StéphaneChazelas 그래, 좋아, 내가 선택한 단어가 더 좋았을 수도 있지만, 사용자에 대한 순 효과는 거의 같습니다. 복잡성에 얽매이지 않고 단어를 약간 변경할 수 있는지 살펴 보겠습니다.
roaima

토론하는 문제를 겪지 않고 중간 하위 디렉토리 경로를 포함시키지 않으면 zip 파일의 압축을 해제하는 방법이 궁금하십니까?
Octopus

1
@Octopus OP는 zip 파일에 " 선택된 파일, 파일 이름 목록으로 제공 "이 포함되어 있다고 명시하고 있습니다 .
roaima

zip -j - ...출력 스트림을 사용하여 클라이언트의 네트워크 연결에 직접 파이핑하는 것이 좋습니다 zip -j zipfile.zip .... 실제 zip 파일을 디스크에 쓰는 것은 데이터 경로가 디스크-> 압축-> 디스크로 쓰기-> 디스크에서 읽기-> 클라이언트로 전송됨을 의미합니다. 이는 디스크-> 압축-> 클라이언트로의 읽기보다 디스크 IO 요구 사항을 최대 3 배 까지 높일 수 있습니다 .
Andrew Henle

5

영화, TV 및 비디오 게임용 데이터베이스를 처리하는 웹 사이트를 운영합니다. 이들 각각에 대해 TV에는 쇼당 수십 개의 이미지가 포함 된 여러 이미지가 있습니다 (예 : 에피소드 스냅 샷 등).

많은 이미지 파일이 있습니다. 250,000 개 이상의 어딘가에 있습니다. 이들은 모두 액세스 시간이 적당한 마운트 된 블록 스토리지 장치에 저장됩니다.

이미지를 저장하려는 첫 번째 시도는 단일 폴더에 /mnt/images/UUID.jpg

나는 다음과 같은 도전에 부딪쳤다.

  • ls원격 터미널을 통해 중단됩니다. 프로세스는 좀비가되어 CTRL+C깨뜨리지 않습니다.
  • 그 지점에 도달하기 전에 모든 ls명령은 출력 버퍼를 빠르게 채우고 CTRL+C끝없는 스크롤을 멈추지 않습니다.
  • 단일 폴더에서 250,000 개의 파일을 압축하는 데 약 2 시간이 걸렸습니다. 터미널에서 zip 명령을 분리하여 실행해야합니다. 그렇지 않으면 연결이 중단되면 다시 시작해야합니다.
  • Windows에서 zip 파일을 사용하려고해도 위험하지 않습니다.
  • 이 폴더는 빠르게 사람이 허용하지 않는 영역이되었습니다.

경로를 만들기 위해 생성 시간을 사용하여 파일을 하위 폴더에 저장해야했습니다. 와 같은 /mnt/images/YYYY/MM/DD/UUID.jpg. 이것은 위의 모든 문제를 해결하고 날짜를 목표로 한 zip 파일을 만들 수있게했습니다.

파일의 유일한 식별자가 숫자이고이 숫자가 순서대로 실행되는 경우 왜으로 그룹을 100000, 10000하고 1000.

예를 들어, 파일 이름 384295.txt이 경로 인 경우 :

/mnt/file/300000/80000/4000/295.txt

아시면 몇 백만에 도달 할 것입니다. 01,000,000에 접두사 사용

/mnt/file/000000/300000/80000/4000/295.txt

1

웹 스크랩에서 텍스트 파일을 작성합니다 (폴더의 파일 수에 영향을받지 않아야 함).

새 파일을 작성하려면 새 디렉토리 항목을위한 충분한 빈 공간을 찾기 위해 디렉토리 파일을 스캔해야합니다. 새 디렉토리 항목을 저장하기에 충분한 공간이 없으면 디렉토리 파일의 끝에 배치됩니다. 디렉토리의 파일 수가 증가함에 따라 디렉토리를 스캔하는 시간도 늘어납니다.

디렉토리 파일이 시스템 캐시에 남아있는 한, 이로 인한 성능 저하는 나쁘지 않지만 데이터가 해제되면 디스크에서 디렉토리 파일 (일반적으로 조각화 됨)을 읽는 데 상당한 시간이 소요될 수 있습니다. SSD는이를 개선하지만 수백만 개의 파일이있는 디렉토리의 경우 여전히 눈에 띄는 성능 저하가있을 수 있습니다.

파일 이름 목록에 따라 선택된 파일을 압축합니다.

또한 수백만 개의 파일이있는 디렉토리에서 추가 시간이 필요할 수 있습니다. EXT4와 같은 해시 디렉토리 항목이있는 파일 시스템에서이 차이는 최소화됩니다.

폴더에 최대 천만 개의 파일을 저장하면 파일을 저장할 하위 폴더 트리를 만드는 것과 다른 방식으로 위 작업의 성능 또는 일반 시스템 성능에 영향을 줍니까?

하위 폴더 트리에는 위의 성능 단점이 없습니다. 또한 기본 파일 시스템이 해시 파일 이름을 갖지 않도록 변경 되어도 트리 방법론은 여전히 ​​잘 작동합니다.


1

첫째 : 'ls'가 'ls -U'로 정렬되지 않도록 ~ / bashrc를 'alias ls = "ls -U"'또는 유사하게 업데이트하십시오.

큰 파일 세트의 경우 다음과 같이 시도해 볼 수 있습니다.

  • 테스트 파일 세트를 만듭니다.

  • 많은 파일 이름으로 인해 문제가 발생하는지 확인

  • xargs 매개 변수 배치 및 zip (기본) 동작을 사용하여 파일을 zip에 추가하면 문제가 발생하지 않습니다.

이것은 잘 작동했습니다 :

# create ~ 100k files
seq 1 99999 | sed "s/\(.*\)/a_somewhat_long_filename_as_a_prefix_to_exercise_zip_parameter_processing_\1.txt/" | xargs touch
# see if zip can handle such a list of names
zip -q /tmp/bar.zip ./*
    bash: /usr/bin/zip: Argument list too long
# use xargs to batch sets of filenames to zip
find . -type f | xargs zip -q /tmp/foo.zip
l /tmp/foo.zip
    28692 -rw-r--r-- 1 jmullee jmullee 29377592 2017-12-16 20:12 /tmp/foo.zip
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.