PostgreSQL ofrece una buena interfaz de BLOBS que se usa ampliamente. Sin embargo, recientemente nos encontramos con problemas enfrentados por varios clientes, y tiene sentido reflexionar un poco y averiguar cómo PostgreSQL maneja los BLOBs, y especialmente la limpieza de BLOBS.

Usando la interfaz de BLOB de PostgreSQL

En PostgreSQL, puede usar varios medios para almacenar datos binarios. La forma más simple es definitivamente hacer uso del tipo de datos» bytea » (=matriz de bytes). En este caso, un campo binario se ve básicamente como parte de una fila.
Así es como funciona:

Como puede ver, esta es una columna normal y se puede usar como una columna normal. Lo único que vale la pena mencionar es la codificación que se tiene que usar en el nivel SQL. PostgreSQL utiliza una variable para configurar este comportamiento:

test=# SHOW bytea_output;bytea_output--------------hex(1 row)

La variable bytea_output acepta dos valores: «hex» le dice a PostgreSQL que envíe los datos en formato hex. «escape» significa que los datos deben ser introducidos como una cadena octal. No hay mucho de lo que la aplicación tenga que preocuparse aquí, aparte del tamaño máximo de 1 GB por campo.
Sin embargo, PostgreSQL tiene una segunda interfaz para manejar datos binarios: La interfaz BLOB. Permítanme mostrar un ejemplo de esta poderosa herramienta en acción:

test=# SELECT lo_import('/etc/hosts');lo_import-----------80343(1 row)

En este caso, el contenido de /etc/hosts se ha importado a la base de datos. Tenga en cuenta que PostgreSQL tiene una copia de los datos – no es un enlace al sistema de archivos. Lo que es notable aquí es que la base de datos devolverá el OID (ID de objeto) de la nueva entrada. Para realizar un seguimiento de estos OID, algunos desarrolladores hacen lo siguiente:

INSERT 0 1

Esto está absolutamente bien, a menos que hagas algo como a continuación:

test=# DELETE FROM t_file WHERE id = 1;DELETE 1

El problema es que el id del objeto se ha olvidado. Sin embargo, el objeto sigue ahí. pg_largeobject es la tabla del sistema encargada de almacenar los datos binarios dentro de PostgreSQL. Todas las funciones lo_ simplemente hablarán con esta tabla del sistema para manejar estas cosas:

¿Por qué es un problema? La razón es simple: Su base de datos crecerá y el número de «objetos muertos» se acumulará. Por lo tanto, la forma correcta de eliminar una entrada de BLOB es la siguiente:

Si olvida desvincular el objeto, sufrirá a largo plazo – y a menudo hemos visto que eso sucede. Es un problema importante si está utilizando la interfaz de BLOB.

vacuumlo: Limpieza de objetos grandes muertos

Sin embargo, ¿cómo se puede solucionar el problema una vez que se han acumulado miles, o tal vez millones, de manchas muertas? La respuesta es una herramienta de línea de comandos llamada «vacuumlo».
Primero vamos a crear una entrada muerta:

test=# SELECT lo_import('/etc/hosts');lo_import-----------80351(1 row)

Luego podemos ejecutar vacuumlo desde cualquier cliente:

Como puede ver, la herramienta ha matado dos objetos muertos. vacuumlo es la forma más fácil de limpiar objetos huérfanos.

Funcionalidad adicional

Sin embargo, hay más que solo lo_import y lo_unlink. PostgreSQL ofrece una variedad de funciones para manejar objetos grandes de una manera agradable:

Hay dos funciones más que no siguen la convención de nomenclatura por razones históricas: loread y lowrite:

pg_catalog | loread | bytea | integer, integer | funcpg_catalog | lowrite | integer | integer, bytea | func

Son funciones cuyos nombres ya no se pueden cambiar fácilmente. Sin embargo, vale la pena señalar que existen.

Finalmente

La interfaz de BLOB de PostgreSQL es realmente útil y se puede usar para muchas cosas. La belleza es que es totalmente transaccional y, por lo tanto, el contenido binario y los metadatos ya no pueden desconectarse.

Si desea obtener más información sobre disparadores para aplicar restricciones en PostgreSQL, le recomendamos que consulte nuestra publicación de blog escrita por Laurenz Albe. Arrojará algo de luz sobre este importante tema.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.