在大型csv文件中搜索

时间:2018-05-29 18:02:18

标签: mysql shell csv search grep

问题

我在一个文件夹中有数千个csv文件。每个文件都有128,000个条目,每行有四列。 有时(每天两次)我需要将列表(10,000个条目)与所有csv文件进行比较。如果其中一个条目与其中一个csv文件的第三列或第四列相同,我需要将整个csv行写入一个额外的文件。

可能的解决方案

grep的

#!/bin/bash
getArray() {
    array=()
    while IFS= read -r line
    do
        array+=("$line")
    done < "$1"
}

getArray "entries.log"
for e in "${array[@]}"
do
    echo "$e"
    /bin/grep $e ./csv/* >> found
done

这似乎有效,但它会持续下去。在将近48小时后,该脚本仅检查了大约10,000个条目中的48个条目。

的MySQL

下一个尝试是将所有csv文件导入mysql数据库。但是我的桌子上有大约50,000,000个条目存在问题。 所以我编写了一个脚本,在49,000,000个条目之后创建了一个新表,因此我能够导入所有csv文件。 我试图在第二列创建一个索引,但它总是失败(超时)。在导入过程不可能之前创建索引。它将导入速度减慢到几天而不是几个小时。 选择声明很糟糕,但它奏效了。比“grep”解决方案快得多,但仍然会变慢。

我的问题

我还可以尝试在csv文件中搜索什么? 为了加快速度,我将所有csv文件复制到ssd。但我希望还有其他方法。

3 个答案:

答案 0 :(得分:0)

这不太可能为您提供有意义的好处,但对您的脚本进行了一些改进

  1. 使用内置的mapfile将文件粘贴到数组中:

    mapfile -t array < entries.log
    
  2. 将grep与模式和适当标志文件一起使用。

    我假设您希望将entries.log中的项目与固定字符串匹配,而不是正则表达式模式 我还假设你想要匹配整个单词。

    grep -Fwf entries.log ./csv/*
    

    这意味着您不必花费1000次csv文件(对于entries.log中的每个项目一次)。实际上,仅此应该为您提供真正有意义的性能提升。

    这也消除了将entries.log读入数组的需要。

答案 1 :(得分:0)

您可以构建一个模式文件,然后使用xargsgrep -Ef来搜索批量csv文件中的所有模式,而不是像当前解决方案中那样一次搜索一个模式:

# prepare patterns file
while read -r line; do
  printf '%s\n' "^[^,]+,[^,]+,$line,[^,]+$"       # find value in third column
  printf '%s\n' "^[^,]+,[^,]+,[^,]+,$line$"       # find value in fourth column
done < entries.log > patterns.dat

find /path/to/csv -type f -name '*.csv' -print0 | xargs -0 grep -hEf patterns.dat > found.dat
  • find ... - 发出所有找到的csv文件的NUL分隔列表
  • xargs -0 ... - 将文件列表批量传递给grep

答案 2 :(得分:0)

在awk中假设所有csv文件都发生了变化,否则跟踪已经检查过的文件是明智的。但首先是一些测试材料:

$ mkdir test        # the csvs go here
$ cat > test/file1  # has a match in 3rd
not not this not
$ cat > test/file2  # no match
not not not not
$ cat > test/file3  # has a match in 4th
not not not that
$ cat > list        # these we look for
this
that

然后是剧本:

$ awk 'NR==FNR{a[$1];next} ($3 in a) || ($4 in a){print >> "out"}' list test/*
$ cat out
not not this not
not not not that

说明:

$ awk '                   # awk
NR==FNR {                 # process the list file
    a[$1]                 # hash list entries to a
    next                  # next list item
} 
($3 in a) || ($4 in a) {  # if 3rd or 4th field entry in hash
    print >> "out"        # append whole record to file "out"
}' list test/*            # first list then the rest of the files

该脚本将所有列表条目哈希到a并通过csv文件读取,以便在匹配时查找哈希输出中的第3和第4个字段条目。

如果您测试它,请告诉我它运行了多长时间。