我有一个基于 65536 个文件的平面数据库,每个文件包含一个以两个十六进制字符开头的逐行单词。
它们看起来像这样:
afword
46word2
Feword3
...
我每天对此发出数以万计的请求,因此我正在寻找一种更好的方法来查找以两个十六进制字符开头的行。文件在 gzip 之前已排序。
截至目前,我这样做:
LC=ALL zgrep --text '^af' file
有没有其他更快的方法可以在 perl 或 bash 或任何命令行中执行此操作?
答案1
zgrep
(附带的gzip
)是一个 shell 脚本,它最终会执行类似的操作zcat | grep
。其功能与此zutils
相同,只是它是用 C++ 编写的并且支持更多压缩格式。它仍然在单独的进程中调用gzip
and grep
,并通过管道连接。
通过如此简单的搜索,grep
工作比 简单得多zcat
,因此,如果您保持相同的方法来组织数据,我建议集中精力改进事物的压缩方面。
在这里处理使用 生成的文件时xxd -p -c35 < /dev/urandom | head -n 760000 | sort
,我发现它经过 gzip 压缩,使用pigz -dc
而不是zcat
(又名gzip -dc
)将速度提高了 2 倍。
使用 对其进行压缩lz4 --best
,我得到的文件大了 30%,但解压时间减少了 100 倍:
$ zstat +size a*(m-1)| sort -k2n | column -t
a.xz 26954744
a.lrz 26971363
a.bz2 27412562
a.gz 30353089
a.gz3 30727911
a.lzop 38000050
a.lz4 40261510
a 53960000
$ time lz4cat a.lz4 > /dev/null
lz4cat a.lz4 > /dev/null 0.06s user 0.01s system 98% cpu 0.064 total
$ time pigz -dc a.gz > /dev/null
pigz -dc a.gz > /dev/null 0.36s user 0.02s system 126% cpu 0.298 total
$ time gzip -dc a.gz > /dev/null
gzip -dc a.gz > /dev/null 0.47s user 0.00s system 99% cpu 0.476 total
$ time lz4cat a.lz4 | LC_ALL=C grep '^af' > /dev/null
lz4cat a.lz4 0.07s user 0.02s system 60% cpu 0.142 total
LC_ALL=C grep '^af' > /dev/null 0.07s user 0.00s system 53% cpu 0.141 total
$ time pigz -dc a.gz | LC_ALL=C grep '^af' > /dev/null
pigz -dc a.gz 0.36s user 0.04s system 130% cpu 0.303 total
LC_ALL=C grep '^af' > /dev/null 0.06s user 0.01s system 23% cpu 0.302 total
$ time gzip -dc a.gz | LC_ALL=C grep '^af' > /dev/null
gzip -dc a.gz 0.51s user 0.00s system 99% cpu 0.513 total
LC_ALL=C grep '^af' > /dev/null 0.08s user 0.01s system 16% cpu 0.512 total
lzop --best
紧随其后lz4
,并且在我的样本上压缩得稍好一些。
$ time lzop -dc a.lzop | LC_ALL=C grep '^af' > /dev/null
lzop -dc a.lzop 0.24s user 0.01s system 85% cpu 0.293 total
LC_ALL=C grep '^af' > /dev/null 0.07s user 0.01s system 27% cpu 0.292 total