J'ai expliqué une situation similaire avec des fichiers en texte brut sur Grep un grand nombre de modèles à partir d'un fichier énorme. Beaucoup de gens ont dit que je devrais le faire, alors maintenant je migre mes données vers une base de données sqlite :
J'ai un fichier dont j'extrait environ 10 000 motifs. Ensuite, je vérifie si la base de données ne contient pas de tels modèles. Si ce n'est pas le cas, je dois les enregistrer en externe dans le file
pour un traitement ultérieur :
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
Depuis que je suis nouveau sur SQL, je n'ai pas trouvé de moyen simple de le faire. De plus, cette boucle est inutile car elle est 20 fois plus lente que ce que j'ai réalisé avec awk
sur l'URL mentionnée.
Étant donné que la base de données est énorme, ne cesse de croître et que j'exécute cette boucle très fréquemment, est-il possible de l'accélérer ?
Réponse acceptée :
Pour chaque modèle, vous appelez une nouvelle instance de sqlite
programme qui se connecte à nouveau à la base de données. C'est un gaspillage. Vous devez créer une requête unique qui recherche l'une des clés, puis exécuter cette requête. Les clients de base de données sont bons pour exécuter des requêtes volumineuses.
Si les lignes correspondantes dans les keys
le fichier ne contient que des chiffres, vous pouvez créer la requête comme suit :
{
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
Pour des données d'entrée plus générales, vous voyez l'idée :utilisez des transformations de texte pour créer une seule grande requête. Veillez à valider votre entrée ; ici, nous nous assurons que ce qui est injecté dans la requête est syntaxiquement valide. Il y a en fait un cas particulier dans l'exemple ci-dessus :s'il n'y a pas de correspondance dans le fichier, alors la syntaxe SQL est invalide; si cela devait arriver, vous devrez traiter ce cas spécialement. Voici un code plus complexe qui prend en charge le cas vide :
<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