Grepping a huge file (80GB) any way to speed it up?

 grep -i -A 5 -B 5 'db_pd.Clients'  eightygigsfile.sql

This has been running for an hour on a fairly powerful linux server which is otherwise not overloaded. Any alternative to grep? Anything about my syntax that can be improved, (egrep,fgrep better?)

The file is actually in a directory which is shared with a mount to another server but the actual diskspace is local so that shouldn't make any difference?

the grep is grabbing up to 93% CPU

96311 次浏览

两条进攻路线:

  • 你确定,你需要 -i,或者你有可能摆脱它?
  • 你还有更多的内核可以玩吗?grep是单线程的,因此您可能需要在不同的偏移量下启动更多的 grep

一些微不足道的改进:

  • 删除-i 选项,如果可以的话,不区分大小写是相当慢的。

  • \.代替 .

    单点是匹配任何字符的正则表达式符号,这也很慢

下面是一些选择:

1)在 grep 命令前面加上 LC_ALL=C,使用 C 语言环境而不是 UTF-8。

2)使用 fgrep,因为您搜索的是固定的字符串,而不是正则表达式。

3)删除 -i选项,如果你不需要它。

所以你的命令是:

LC_ALL=C fgrep -A 5 -B 5 'db_pd.Clients' eightygigsfile.sql

如果您将您的文件复制到 RAM 磁盘,它也会更快。

如果你有一个多核 CPU,我真的推荐 GNU 并行。要并行使用一个大文件:

< eightygigsfile.sql parallel --pipe grep -i -C 5 'db_pd.Clients'

根据磁盘和 CPU 的不同,读取较大的块可能更快:

< eightygigsfile.sql parallel --pipe --block 10M grep -i -C 5 'db_pd.Clients'

你的问题并不完全清楚,但 grep的其他选择包括:

  • 放下 -i的旗帜。
  • 对固定字符串使用 -F标志
  • LANG=C禁用 NLS
  • 使用 -m标志设置最大匹配数。
< eightygigsfile.sql parallel -k -j120% -n10 -m grep -F -i -C 5 'db_pd.Clients'

如果需要搜索多个字符串,grep-f strings.txt 可以节省大量时间。以上是我目前正在测试的东西的翻译。J 和-n 选项值似乎对我的用例最有效。F grep 也产生了很大的不同。

试试 Ripgrep

与 grep 相比,它提供了更好的结果。

以上所有的回答都很棒。对我的111GB 文件真正有帮助的是使用 LC _ ALL = C fgrep-m < maxnum > fix _ string 文件名。

但是,有时可能会有0个或更多的重复模式,在这种情况下,计算最大值是不可能的。解决方案是对您试图处理的事件使用开始和结束模式,然后处理它们之间的行号。像这样

startline=$(grep -n -m 1 "$start_pattern"  file|awk -F":" {'print $1'})
endline=$(grep -n -m 1 "$end_pattern"  file |awk -F":" {'print $1'})
logs=$(tail -n +$startline file |head -n $(($endline - $startline + 1)))

然后处理这个日志子集!

嗯..。你需要什么速度?我创建了一个合成的 77.6 GB文件,其中几乎包含了 525 mn行和大量 Unicode:

rows = 524759550. | UTF8 chars = 54008311367. | bytes = 83332269969.

以及在平均值中随机选择的行。速率 1 every 3^5,使用 rand()而不仅仅是 NR % 243,将字符串 db_pd.Clients放置在现有文本中间的一个随机位置,在正则表达式模式命中的位置合计为 2.16 mn rows

rows       = 2160088. | UTF8 chars = 42286394. | bytes = 42286394.




% dtp;  pvE0 < testfile_gigantic_001.txt|
mawk2 '
_^(_<_)<NF { print (__=NR-(_+=(_^=_<_)+(++_)))<!_\
?_~_:__,++__+_+_ }' FS='db_pd[.]Clients' OFS=','


in0: 77.6GiB 0:00:59 [1.31GiB/s] [1.31GiB/s] [===>] 100%
out9: 40.3MiB 0:00:59 [ 699KiB/s] [ 699KiB/s] [ <=> ]
  

524755459,524755470
524756132,524756143
524756326,524756337
524756548,524756559
524756782,524756793
524756998,524757009
524757361,524757372

mawk2只需要 59 seconds提取出它需要的行范围列表。从这里开始,它应该是相对微不足道的。可能存在一些重叠。

1.3GiB/s的吞吐率下,如上面由 pv计算的,使用像 parallel这样的工具来分割任务甚至可能是有害的。