Bagaimana cara menyortir file besar?

35

Saya memiliki PC dengan Intel (R) Pentium (R) CPU G640 @ 2.80 GHz dan 8 GB RAM. Saya menjalankan Scientific Linux 6.5 di atasnya dengan sistem file EXT3.

Pada pengaturan ini, apa cara tercepat yang dapat saya lakukan sort -upada file 200 gigabyte?

Haruskah saya membagi file menjadi file yang lebih kecil (lebih kecil dari 8 GB), sort -umenggabungkannya, lalu membaginya lagi dalam ukuran yang berbeda, sort -ulagi, dll? Atau ada skrip penyortiran, program yang dapat menangani file sebesar ini dengan jumlah RAM yang terbatas?

evachristine
sumber
6
Harap edit pertanyaan Anda dan jelaskan apa yang terjadi ketika Anda mencoba perintah yang Anda kirim. Apakah Anda kehabisan ruang disk? Perintah harus bekerja selama Anda memiliki cukup ruang kosong di /tmp.
terdon
1
Jawaban yang dipilih pada dasarnya mengatakan apa yang dikatakan @terdon, tetapi juga periksa yang ini - stackoverflow.com/a/13025731/2801913 . Anda akan memerlukan GNU paralleluntuk ini, saya pikir daripada moreutils parallelyang diinstal secara default pada beberapa sistem.
Graeme
1
Anda dapat mengunggah file ke Amazon S3, lalu memutar pekerjaan Elastic Map Reduce dengan beberapa ratus node untuk mengurutkannya!
Alan Shutko
2
sort(1)bisa kehabisan ruang pada /tmp; jika demikian, Anda dapat menunjuk area lain untuk file sementara dengan variabel lingkungan TMPDIR, atau flag-T=<tmpdir>
vonbrand

Jawaban:

46

GNU sort(yang merupakan standar pada kebanyakan sistem Linux), memiliki --parallelopsi. Dari http://www.gnu.org/software/coreutils/manual/html_node/sort-invocation.html :

'--parallel = n'

Atur jumlah macam yang dijalankan secara paralel ke n. Secara default, n diatur ke jumlah prosesor yang tersedia, tetapi terbatas pada 8, karena ada peningkatan perolehan kinerja setelah itu. Perhatikan juga bahwa menggunakan n utas meningkatkan penggunaan memori oleh faktor log n. Lihat juga permohonan nproc.

Karena cpu Anda memiliki 2 core, Anda dapat melakukan:

sort --parallel=2 -uo list-sorted.txt list.txt

Lebih baik untuk menentukan jumlah core yang sebenarnya karena mungkin ada lebih karena prosesor memiliki hyper-threading .

Anda juga dapat bereksperimen dengan niceuntuk mempengaruhi prioritas penjadwalan prosesor dan ioniceuntuk mempengaruhi penjadwalan I / O. Anda dapat meningkatkan prioritas daripada proses lain seperti ini, saya tidak berpikir ini akan memberi Anda penghematan besar karena biasanya lebih baik untuk memastikan proses latar belakang tidak menggunakan terlalu banyak sumber daya. Anda dapat memadukannya dengan sesuatu seperti:

nice -n -20 ionice -c2 -n7 sort --parallel=2 -uo list-sorted.txt list.txt

Perhatikan juga bahwa ketika Gilles berkomentar, menggunakan perintah penyortiran GNU tunggal akan lebih cepat daripada metode lain untuk memilah penyortiran karena algoritma sudah dioptimalkan untuk menangani file besar. Hal lain kemungkinan akan memperlambat segalanya.

Graeme
sumber
10
Dan Anda harus mencatat bahwa menelepon sortsecara langsung lebih baik daripada apa pun yang Anda bisa lakukan. GNU sort dirancang untuk mengatasi dengan baik file yang jauh lebih besar dari RAM.
Gilles 'SANGAT berhenti menjadi jahat'
Opsi sortir --parallel tidak berfungsi pada server RH6.5 saya. Sortir --version mengira itu keluar dari coreutils 8.4. Versi mana yang saya perlukan untuk versi paralel?
markus_b
3
Lihat juga superuser.com/questions/938558/sort-parallel-isnt-parallelizing - Anda mungkin harus menentukan sesuatu seperti -S512M jika Anda perhatikan itu bukan paralelisasi.
Unhammer
46

Menggunakan sortperintah mungkin akan menjadi opsi tercepat.

Tetapi Anda mungkin ingin memperbaiki lokal ke C.

sort -utidak melaporkan garis unik, tetapi satu dari setiap rangkaian garis yang sama. Di C locale, 2 baris yang berbeda tentu tidak mengurutkan yang sama, tapi itu tidak terjadi di sebagian besar lokal berbasis UTF-8 pada sistem GNU.

Juga, menggunakan lokal C menghindari overhead karena harus mengurai UTF-8 dan memproses pesanan sortir yang kompleks sehingga akan meningkatkan kinerja secara dramatis.

Begitu:

LC_ALL=C sort -u file

Anda juga dapat meningkatkan kinerja dengan menggunakan drive yang lebih cepat (atau drive yang berbeda dari drive tempat file input dan / atau output) untuk file sementara (menggunakan -Tatau $TMPDIRvariabel lingkungan), atau dengan mengutak-atik -Sopsi yang didukung oleh beberapa sortimplementasi) .

Untuk beberapa jenis input atau penyimpanan lambat, menggunakan --compress-programopsi GNU sort(misalnya dengan lzop) dapat meningkatkan kinerja selain penggunaan penyimpanan.


Sekarang hanya sebuah catatan untuk mereka yang keberatan (sampai batas tertentu) bahwa itu tidak akan menjadi urutan yang benar :

Saya setuju bahwa sebagai manusia, saya ingin melihat Stéphane berada di antara Stefan dan Stephanie , tetapi:

  • Sebuah komputer ingin Stéphane untuk mengurutkan setelahnya é(setidaknya ketika dinyatakan sebagai U + 00E9) sebagai karakter atau byte dari jenis pengkodean UTF-8 setelahnya (dalam hal nilai codepoint atau byte). Itu semacam urutan yang sangat sederhana untuk diterapkan dan merupakan urutan total yang ketat dan tidak mengejutkan.
  • Urutan lokal Anda kemungkinan tidak akan memuaskan dalam banyak kasus bahkan untuk manusia. Misalnya pada sistem saya dengan lokal en_GB.utf8 default:

    • Stéphane dan Stéphane (satu dengan U + 00E9, yang lainnya dengan eU + 0301) tidak mengurutkan yang sama:

      $ printf '%b\n' 'Ste\u0301phane' 'St\u00e9phane' | sort -u
      Stéphane
      Stéphane
      
    • tapi ③, ①, ② semuanya mengurutkan yang sama (jelas bug dalam definisi lokal tersebut):

      $ printf '%s\n' ③ ① ② | sort -u
      ③
      

      Di sini, ini ③, tapi bisa juga ① atau ②

Jadi IMO, kemungkinan Anda selalu ingin sort -udengan LC_ALL = C, jika Anda ingin garis yang unik. Dan jika Anda ingin daftar yang dihasilkan diurutkan dalam urutan pengurutan pengguna, kirimkan kembali ke sort:

LC_ALL=C sort -u | sort

LC_ALL=C sort | LC_ALL=C uniq -c | sort -k2
Stéphane Chazelas
sumber
8
+1 untuk menetapkan lokal: ini dapat memiliki efek besar pada kinerja
Adrian Pronk
1
Iya nih. mengurutkan file dengan 2.500 baris LC_ALL mempercepat hal-hal 8 kali.
Jan Vlcinsky
-1

Berikut ini adalah skrip bash yang siap digunakan untuk menyortir data skala TB pada mesin reguler dengan beberapa ram RAM: http://sgolconda.blogspot.com/2015/11/sort-very-large-dataset.html Ini memeriksa jumlah core mesin Anda sebagai dan menggunakan semua core. Dapat mengurutkan, angka atau file string. Dapat digunakan untuk menemukan catatan unik dalam data skala TB.

pengguna213743
sumber
Ini bukan saran yang bagus. Skrip ini sangat membengkak dan membelah file input untuk mengurutkan bagian-bagian yang ditunjukkan oleh jawaban yang diterima tidak diperlukan dengan jenis GNU.
Thorbjørn Ravn Andersen