Expliqué una situación similar con archivos de texto sin formato en Grep, una gran cantidad de patrones de un archivo enorme. Mucha gente allí dijo que debería, así que ahora estoy migrando mis datos a una base de datos sqlite:
Tengo un archivo del que extraigo unos 10.000 patrones. Luego verifico si la base de datos no contiene tales patrones. Si no es así, necesito guardarlos externamente en file
para su posterior procesamiento:
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
Como soy nuevo en SQL, no pude encontrar una manera simple de hacer esto. Además, este ciclo es inútil ya que es 20 veces más lento que lo que logré con awk
en la URL mencionada.
Dado que la base de datos es enorme, sigue creciendo y ejecuto este ciclo con mucha frecuencia, ¿es posible hacerlo más rápido?
Respuesta aceptada:
Para cada patrón, está invocando una nueva instancia de sqlite
programa que se conecta a la base de datos de nuevo. Eso es un desperdicio. Debe crear una sola consulta que busque cualquiera de las claves y luego ejecutar esa consulta. Los clientes de bases de datos son buenos para ejecutar consultas grandes.
Si las líneas coincidentes en las keys
archivo solo contiene dígitos, entonces puede construir la consulta de la siguiente manera:
{
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
Para datos de entrada más generales, tiene la idea:use transformaciones de texto para crear una sola consulta grande. Tenga cuidado de validar su entrada; aquí nos aseguramos de que lo que se inyecta en la consulta sea sintácticamente válido. En realidad, hay un caso de esquina en el ejemplo anterior:si no hay ninguna coincidencia en el archivo, entonces la sintaxis SQL no es válida; si eso puede suceder, deberá tratar este caso de manera especial. Aquí hay un código más complejo que se ocupa del caso vacío:
<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