巨大なファイルからのGrepの膨大な数のパターンのプレーンテキストファイルで同様の状況を説明しました。そこにいる多くの人が私がすべきだと言ったので、今私は自分のデータをsqliteデータベースに移行しています:
約10,000個のパターンを抽出したファイルがあります。次に、データベースにそのようなパターンが含まれていないかどうかを確認します。そうでない場合は、外部のfile
に保存する必要があります さらなる処理のために:
for id in $(grep ^[0-9] keys); do
if [[ -z $(sqlite3 db.sqlite "select id from main where id = $id") ]]; then
echo $id >>file
fi
done
私はSQLを初めて使用するため、これを行う簡単な方法を見つけることができませんでした。また、このループは、awk
で達成したものよりも20倍遅いため、役に立ちません。 上記のURLで。
データベースは巨大で、増え続けており、このループを頻繁に実行しているので、これを高速化することは可能ですか?
承認された回答:
パターンごとに、sqlite
の新しいインスタンスを呼び出します。 新たにデータベースに接続するプログラム。それは無駄です。いずれかのキーを検索する単一のクエリを作成してから、その1つのクエリを実行する必要があります。データベースクライアントは、大規模なクエリの実行に優れています。
keys
の一致する行の場合 ファイルに数字のみが含まれている場合は、次のようにクエリを作成できます。
{
echo 'select id from main where id in (';
<keys grep -x '[0-9][0-9]*' | # retain only lines containing only digits
sed -e '1! s/^/, /' | # add ", " at the beginning of every line except the first
echo ');'
} | sqlite3 db.sqlite
より一般的な入力データについては、テキスト変換を使用して単一の大きなクエリを作成するというアイデアが得られます。入力を検証するように注意してください。ここでは、クエリに挿入されるものが構文的に有効であることを確認します。上記の例には、実際にはコーナーケースがあります。ファイルに一致するものがない場合、SQL構文は無効です。それが発生する可能性がある場合は、このケースを特別に処理する必要があります。空のケースを処理するより複雑なコードは次のとおりです。
<keys grep -x '[0-9][0-9]*' |
if read first; then {
echo 'select id from main where id in (' "$first"
sed -e 's/^/, /'
echo ');'
} | sqlite3 db.sqlite
fi