Kami ingin menyimpan jutaan file teks dalam sistem file Linux, dengan tujuan dapat melakukan zip up dan melayani koleksi sewenang-wenang sebagai layanan. Kami telah mencoba solusi lain, seperti database kunci / nilai, tetapi persyaratan kami untuk konkurensi dan paralelisme menjadikan penggunaan sistem file asli sebagai pilihan terbaik.
Cara paling mudah adalah dengan menyimpan semua file dalam folder:
$ ls text_files/
1.txt
2.txt
3.txt
yang seharusnya dimungkinkan pada sistem file EXT4 , yang tidak memiliki batasan jumlah file dalam folder.
Dua proses FS adalah:
- Tulis file teks dari goresan web (tidak boleh dipengaruhi oleh jumlah file di folder).
- Zip file yang dipilih, diberikan oleh daftar nama file.
Pertanyaan saya adalah, apakah menyimpan hingga sepuluh juta file dalam folder memengaruhi kinerja operasi di atas, atau kinerja sistem umum, berbeda dari membuat pohon subfolder untuk file yang akan ditinggali?
files
filesystems
performance
ext4
pengguna1717828
sumber
sumber
dir_index
, yang sering diaktifkan secara default, akan mempercepat pencarian tetapi dapat membatasi jumlah file per direktori.ls -l
atau apa pun yangstat
setiap inode dalam direktori (misalnyabash
globbing / penyelesaian tab) akan secara artifisial lebih cepat daripada setelah beberapa keausan (hapus beberapa file, tulis beberapa yang baru). ext4 mungkin lebih baik dengan ini daripada XFS, karena XFS secara dinamis mengalokasikan ruang untuk inode vs data, sehingga Anda dapat berakhir dengan inode yang lebih tersebar, saya pikir. (Tapi itu dugaan murni berdasarkan sedikit pengetahuan rinci; Saya baru saja menggunakan ext4). Pergi denganabc/def/
subdirs.ZipOutputStream
akan mengalahkan hampir semua sistem file asli Linux gratis - Saya ragu Anda ingin membayar untuk GPFS IBM. Loop untuk memproses set hasil JDBC dan membuat aliran zip mungkin hanya 6-8 baris kode Java.Jawaban:
The
ls
perintah, atau bahkan TAB-selesai atau perluasan wildcard oleh shell, biasanya akan mempresentasikan hasil mereka dalam rangka alfanumerik. Ini membutuhkan membaca seluruh daftar direktori dan menyortirnya. Dengan sepuluh juta file dalam satu direktori, operasi penyortiran ini akan memakan banyak waktu.Jika Anda dapat menahan keinginan untuk menyelesaikan TAB dan misalnya menulis nama file yang akan dizip secara penuh, seharusnya tidak ada masalah.
Masalah lain dengan wildcard mungkin ekspansi wildcard yang mungkin menghasilkan lebih banyak nama file daripada yang sesuai pada baris perintah dengan panjang maksimum. Panjang baris perintah maksimum tipikal akan lebih dari cukup untuk sebagian besar situasi, tetapi ketika kita berbicara tentang jutaan file dalam satu direktori, ini bukan lagi asumsi yang aman. Ketika panjang baris perintah maksimum terlampaui dalam ekspansi wildcard, sebagian besar shell hanya akan gagal seluruh baris perintah tanpa mengeksekusi itu.
Ini dapat diatasi dengan melakukan operasi wildcard Anda menggunakan
find
perintah:atau sintaksis yang serupa bila memungkinkan. Ini
find ... -exec ... \+
akan secara otomatis memperhitungkan panjang baris perintah maksimum, dan akan mengeksekusi perintah sebanyak yang diperlukan sambil menyesuaikan jumlah maksimal nama file untuk setiap baris perintah.sumber
ls
perintah tidak akan mengetahui bahwa daftar direktori sudah diurutkan, mereka akan mengambil waktu untuk menjalankan algoritma penyortiran. Dan selain itu, userspace mungkin menggunakan urutan penyortiran lokal (LC_COLLATE) yang mungkin berbeda dari apa yang mungkin dilakukan sistem file secara internal.Ini sangat dekat dengan pertanyaan / jawaban berdasarkan pendapat tetapi saya akan mencoba untuk memberikan beberapa fakta dengan pendapat saya.
mv * /somewhere/else
) Mungkin gagal untuk memperluas wildcard berhasil, atau hasilnya mungkin terlalu besar untuk digunakan.ls
akan membutuhkan waktu lebih lama untuk menghitung jumlah file yang sangat besar daripada sejumlah kecil file.Satu rekomendasi adalah untuk membagi nama file menjadi dua, tiga atau empat potongan karakter dan menggunakannya sebagai subdirektori. Misalnya,
somefilename.txt
dapat disimpan sebagaisom/efi/somefilename.txt
. Jika Anda menggunakan nama numerik maka pisah dari kanan ke kiri alih-alih kiri ke kanan sehingga ada distribusi yang lebih merata. Misalnya12345.txt
dapat disimpan sebagai345/12/12345.txt
.Anda dapat menggunakan yang setara dengan
zip -j zipfile.zip path1/file1 path2/file2 ...
untuk menghindari termasuk jalur subdirektori antara dalam file ZIP.Jika Anda menyajikan file-file ini dari server web (saya tidak sepenuhnya yakin apakah itu relevan) itu sepele untuk menyembunyikan struktur ini demi direktori virtual dengan aturan penulisan ulang di Apache2. Saya akan menganggap hal yang sama berlaku untuk Nginx.
sumber
*
ekspansi akan berhasil kecuali jika Anda kehabisan memori, tetapi jika Anda menaikkan batas stacksize (di Linux) atau menggunakan shell manamv
adalah builtin atau dapat builtin (ksh93, zsh), yangexecve()
system call mungkin gagal dengan kesalahan E2BIG.zip -j - ...
dan pemipaan aliran output langsung ke koneksi jaringan klienzip -j zipfile.zip ...
. Menulis zipfile aktual ke disk berarti jalur data dibaca dari disk-> kompres-> tulis ke disk-> baca dari disk-> kirim ke klien. Itu bisa tiga kali lipat persyaratan IO disk Anda setelah dibaca dari disk-> kirim-> kirim ke klien.Saya menjalankan situs web yang menangani basis data untuk film, TV, dan permainan video. Untuk masing-masing ini ada beberapa gambar dengan TV yang berisi lusinan gambar per pertunjukan (yaitu foto snapshot dll).
Akhirnya ada banyak file gambar. Di suatu tempat di kisaran 250.000+. Ini semua disimpan dalam perangkat penyimpanan blok yang terpasang di mana waktu akses masuk akal.
Upaya pertama saya menyimpan gambar adalah dalam satu folder sebagai
/mnt/images/UUID.jpg
Saya mengalami tantangan berikut.
ls
melalui terminal jarak jauh hanya akan menggantung. Prosesnya akan menjadi zombie danCTRL+C
tidak akan merusaknya.ls
perintah apa pun akan dengan cepat mengisi buffer output danCTRL+C
tidak akan menghentikan pengguliran tanpa akhir.Saya akhirnya harus menyimpan file dalam subfolder menggunakan waktu pembuatan untuk membuat path. Seperti
/mnt/images/YYYY/MM/DD/UUID.jpg
. Ini menyelesaikan semua masalah di atas, dan memungkinkan saya untuk membuat file zip yang menargetkan tanggal.Jika satu-satunya pengidentifikasi untuk file yang Anda miliki adalah angka numerik, dan angka-angka ini cenderung berjalan berurutan. Mengapa tidak mengelompokkan mereka berdasarkan
100000
,10000
dan1000
.Misalnya, jika Anda memiliki file dengan nama
384295.txt
path akan menjadi:Jika Anda tahu Anda akan mencapai beberapa juta. Gunakan
0
awalan untuk 1.000.000sumber
Untuk membuat file baru diperlukan pemindaian file direktori mencari ruang kosong yang cukup untuk entri direktori baru. Jika tidak ada ruang yang cukup besar untuk menyimpan entri direktori baru, itu akan ditempatkan di akhir file direktori. Ketika jumlah file dalam direktori meningkat, waktu untuk memindai direktori juga meningkat.
Selama file direktori tetap di cache sistem, kinerja yang dihasilkan dari ini tidak akan buruk, tetapi jika data dirilis, membaca file direktori (biasanya sangat terfragmentasi) dari disk dapat menghabiskan waktu yang cukup lama. SSD meningkatkan ini, tetapi untuk direktori dengan jutaan file, masih ada hit kinerja yang terlihat.
Ini juga membutuhkan waktu tambahan dalam direktori dengan jutaan file. Dalam sistem file dengan entri direktori hash (seperti EXT4), perbedaan ini minimal.
Pohon subfolder tidak memiliki kekurangan kinerja di atas. Selain itu, jika sistem file yang mendasarinya diubah menjadi tidak memiliki nama file hash, metodologi pohon akan tetap bekerja dengan baik.
sumber
Pertama: mencegah 'ls' dari pengurutan dengan 'ls -U', mungkin perbarui ~ / bashrc Anda untuk memiliki 'alias ls = "ls -U"' atau serupa.
Untuk kumpulan file besar Anda, Anda dapat mencobanya seperti ini:
buat satu set file uji
lihat apakah banyak nama file yang menyebabkan masalah
gunakan xargs parmeter-batching dan perilaku zip (standar) untuk menambahkan file ke zip untuk menghindari masalah.
Ini bekerja dengan baik:
sumber