Vysvětlil jsem podobnou situaci s prostými textovými soubory na Grepu obrovské množství vzorů z velkého souboru. Mnoho lidí tam řeklo, že bych měl, takže nyní migruji svá data do databáze sqlite:
Mám soubor, ze kterého vytahuji asi 10 000 vzorů. Poté zkontroluji, zda databáze takové vzory neobsahuje. Pokud ne, musím je uložit externě do file
pro další zpracování:
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
Protože jsem v SQL nováčkem, nenašel jsem jednoduchý způsob, jak to udělat. Tato smyčka je také k ničemu, protože je 20krát pomalejší než to, čeho jsem dosáhl pomocí awk
na uvedené adrese URL.
Vzhledem k tomu, že databáze je obrovská, neustále roste a tuto smyčku spouštím velmi často, je možné to zrychlit?
Přijatá odpověď:
Pro každý vzor vyvoláváte novou instanci sqlite
program, který se znovu připojí k databázi. To je plýtvání. Měli byste sestavit jeden dotaz, který hledá kterýkoli z klíčů, a poté provést tento jeden dotaz. Databázoví klienti jsou dobří při provádění velkých dotazů.
Pokud se shodují řádky v keys
obsahuje pouze číslice, pak můžete vytvořit dotaz následovně:
{
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
Pro obecnější vstupní data získáte nápad:pomocí textových transformací sestavte jeden velký dotaz. Buďte opatrní, abyste svůj vstup ověřili; zde se ujistíme, že to, co se vloží do dotazu, je syntakticky platné. Ve výše uvedeném příkladu je ve skutečnosti rohový případ:pokud v souboru není žádná shoda, pak je syntaxe SQL neplatná; pokud k tomu může dojít, budete muset tento případ ošetřit speciálně. Zde je složitější kód, který se stará o prázdný případ:
<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