Na vícejádrovém serveru použijte paralelní GNU k paralelnímu počítání řádků souborů. Po vytištění počtu řádků každého souboru bc sečte všechny počty řádků.
find . -name '*.txt' | parallel 'wc -l {}' 2>/dev/null | paste -sd+ - | bc
Chcete-li ušetřit místo, můžete dokonce uchovávat všechny soubory komprimované. Následující řádek dekomprimuje každý soubor a počítá jeho řádky paralelně, poté sečte všechny počty.
find . -name '*.xz' | parallel 'xzcat {} | wc -l' 2>/dev/null | paste -sd+ - | bc
Podle mého testu mohu ověřit, že Spark-Shell (založený na Scale) je mnohem rychlejší než ostatní nástroje (GREP, SED, AWK, PERL, WC). Zde je výsledek testu, který jsem spustil na souboru, který měl 23782409 řádků
time grep -c $ my_file.txt;
skutečný 0m44,96suser 0m41,59ssys 0m3,09s
time wc -l my_file.txt;
skutečný 0m37,57suser 0m33,48ssys 0m3,97s
time sed -n '$=' my_file.txt;
skutečný 0m38,22suser 0m28,05ssys 0m10,14s
time perl -ne 'END { $_=$.;if(!/^[0-9]+$/){$_=0;};print "$_" }' my_file.txt
;
skutečný 0m23,38suser 0m20,19ssys 0m3,11s
time awk 'END { print NR }' my_file.txt;
skutečný 0m19,90suser 0m16,76ssys 0m3,12s
spark-shell
import org.joda.time._
val t_start = DateTime.now()
sc.textFile("file://my_file.txt").count()
val t_end = DateTime.now()
new Period(t_start, t_end).toStandardSeconds()
res1:org.joda.time.Seconds =PT15S
Váš omezující faktor rychlosti je rychlost I/O vašeho úložného zařízení, takže přepínání mezi jednoduchými programy pro počítání nových řádků/vzorů nepomůže, protože rozdíl v rychlosti provádění mezi těmito programy bude pravděpodobně potlačen pomalejším diskem/úložištěm/ cokoli máte.
Ale pokud máte stejný soubor zkopírovaný mezi disky/zařízeními, nebo je soubor distribuován mezi tyto disky, můžete operaci jistě provést paralelně. Nevím konkrétně o tomto Hadoopu, ale za předpokladu, že můžete číst 10gb soubor ze 4 různých míst, můžete spustit 4 různé procesy počítání řádků, každý v jedné části souboru, a shrnout jejich výsledky:
$ dd bs=4k count=655360 if=/path/to/copy/on/disk/1/file | wc -l &
$ dd bs=4k skip=655360 count=655360 if=/path/to/copy/on/disk/2/file | wc -l &
$ dd bs=4k skip=1310720 count=655360 if=/path/to/copy/on/disk/3/file | wc -l &
$ dd bs=4k skip=1966080 if=/path/to/copy/on/disk/4/file | wc -l &
Všimněte si &
na každém příkazovém řádku, takže všechny poběží paralelně; dd
funguje jako cat
zde, ale dovolte nám určit, kolik bajtů se má číst (count * bs
bajtů) a kolik se má přeskočit na začátku vstupu (skip * bs
bajtů). Funguje v blocích, proto je potřeba zadat bs
jako velikost bloku. V tomto příkladu jsem 10Gb soubor rozdělil na 4 stejné části 4Kb * 655360 =2684354560 bajtů =2,5 GB, jeden pro každou úlohu, možná budete chtít nastavit skript, který to udělá za vás na základě velikosti soubor a počet paralelních úloh, které spustíte. Musíte také sečíst výsledek spouštění, což jsem neudělal kvůli nedostatku schopnosti skriptu shellu.
Pokud je váš souborový systém dostatečně chytrý na to, aby rozdělil velký soubor mezi mnoho zařízení, jako je RAID nebo distribuovaný souborový systém nebo tak něco, a automaticky paralelizoval I/O požadavky, které lze paralelizovat, můžete takové rozdělení provést, spustit mnoho paralelních úloh, ale pomocí stejnou cestu k souboru a stále můžete mít určité zvýšení rychlosti.
EDIT:Další nápad, který mě napadl, je, že pokud mají řádky uvnitř souboru stejnou velikost, můžete získat přesný počet řádků vydělením velikosti souboru velikostí řádku, obojí v bajtech. Můžete to udělat téměř okamžitě v jedné práci. Pokud máte průměrnou velikost a nezáleží vám přesně na počtu řádků, ale chcete odhad, můžete provést stejnou operaci a získat uspokojivý výsledek mnohem rychleji než přesná operace.
Zkuste:sed -n '$=' filename
Také kočka je zbytečná:wc -l filename
stačí vaším současným způsobem.