Es bastante frecuente que en nuestros proyectos con Xojo debamos de trabajar con bases de datos SQLite, protegidas con contraseña, en las que deseemos obtener el máximo rendimiento posible de lectura. Sin embargo, el hecho de que protejamos los contenidos implica una sustancial pérdida en las operaciones de la base de datos, tanto de consulta como de escritura. ¿Cómo resolverlo entonces? La mejor solución pasa por crear una nueva base de datos en memoria, sobre la cual copiaremos la tabla (o tablas) en las que estemos interesados trabajar. A continuación encontrarás como hacerlo.
Esta misma técnica ligeramente adaptada también es la solución a la hora de trabajar con las bases de datos de una forma mixta; es decir, en las que debamos de emplear simultáneamente en una consulta, por ejemplo, tanto tablas disponibles en el archivo de base de datos en disco como aquellas que hayamos creado sobre una base de datos SQLite en memoria.
Sin embargo, el código que encontrarás a continuación es el que te permitirá abrir el archivo de datos SQLite en disco como nueva instancia de la clase SQLite, utilizando a continuación el comando SQL que te permitirá crear una nueva base de datos en memoria, con el nombre RAMDB
, creando a continuación una nueva tabla sobre ella copiando además en la misma instrucción todos los cotenidos desde la tabla fuente correspondiente al archivo en disco. A partir de ese momento, ya podrás trabjar únicamente sobre la tabla situada en la base de datos en memoria (RAMDB
) ¡a la velocidad de la luz!
Otra sentencia que encontrarás interesante, y que puedes utilizar en todas tus bases de datos SQLite para obtener más rendimiento en operaciones de lectura pasa por la activación del modo exclusivo, utilizando para ello la sentencia PRAGMA LOCKING_MODE = Exclusive
.
El fragmento de código para la solución, en definitiva, es el siguiente:
Dim db as SQLiteDatabase = New SQLiteDatabase db.DatabaseFile = // FolderItem al archivo de base de datos SQLite db.EncryptionKey = "aes256:" + // contraseña de acceso a base de datos If db.Connect = False Then Dim re As New RuntimeException re.Reason = "Error al intentar conectar con la base de datos" Raise re End If db.SQLExecute("PRAGMA LOCKING_MODE = Exclusive") // Mejora el rendimiento de acceso en lectura // Creamos la base de datos en memoria y la asociamos con la base de datos actual db.SQLExecute("attach database ':memory:' as 'RAMDB'") // Copiamos todos los contenidos desde la tabla en el archivo de base de datos // a una nueva tabla creada sobre la base de datos en memoria db.SQLExecute("create table RAMDB.product_table as select * from main.product_table")
Como puedes ver, en la segunda línea has de proporcionar una instancia válida a un FolderItem que apunte al archivo de base de datos SQLite. Además, también deberás de añadir el String
correspondiente a la contraseña con la que se hayan cifrado originalmente los contenidos de la base de datos. En este ejemplo se asume que se ha utilizado para ello la opción AES 256 más fuerte en comparación con la logintud de 128 bits empleada con anterioridad a Xojo 2018r1.
Por otra parte, en la última sentencia db.SQLExecute
tendrás que modificar el nombre de la tabla que desees copiar desde la base de datos en disco hacia la nueva base de datos en RAM (en el ejemplo: product_table
).
Pero si esa base de datos es de varios GB, necesitarás toda esa RAM para poder cargarla, y si sólo vas a hacer un par de consultas ¿no es mas costoso tener que cargar toda la base de datos en memoria que dejar al SQLite usar los índices de la base de datos para acceder directamente a lo que se está consultando?
Hola Miguel Ángel,
Evidentemente, no todas las técnicas son aplicables en todos los casos. Este, por ejemplo, claramente no seria uno de ellos en los que puedas sacar el mejor de los provechos. En otros muchos, la capacidad de crear y/o acceder la BBDD en memoria paga con creces el consumo de RAM (cada vez más un recurso MUY disponible en buenas cantidades). Si se mantiene en disco, aparte de los índices conviene aumentar la caché de la BBDD para acelerar aun más el acceso.
Me encanta la idea de tener toda la base montada sobre la RAM.
Un servidor estandar tiene 512 Gb en RAM. y que 50 Gb (y estoy super exagerando) se ocupe por la base de datos no es nada.
SQL Server ocupa mas RAM y no se nota tanto el desempeño comparado con la competencia.