www tutorial servidor portable pagina org oficial create c# sqlite prepared-statement connection-pooling

c# - tutorial - sqlite website



Puesta en común de conexiones SQLite/C#y confusión de sentencias preparadas (2)

He pasado un tiempo leyendo diferentes mejores prácticas para bases de datos y para SQLite específicamente. Mientras leía, descubrí que estaba haciendo muchas cosas que no debería estar haciendo y, al intentar solucionar estos problemas, me confundí al pensar en algunos de los detalles más finos del uso de SQLite con su implementación de ADO.

Mi confusión proviene específicamente de las declaraciones preparadas y la agrupación de conexiones.

Mientras leía http://msdn.microsoft.com/en-us/library/ms971481.aspx encontré que las conexiones solo deberían abrirse para una transacción. Una vez que se completa la transacción, la conexión debe cerrarse. No tengo una idea clara de por qué este es el caso, pero he estado trabajando en la suposición de que el autor sabe mejor que yo. Entiendo que cuando se cierra una conexión no significa que realmente estado cerrado Simplemente significa que ha sido devuelto a la piscina.

Ahora, para mejorar mis consultas e inserciones, leí sobre el uso de declaraciones preparadas. En SQLite, ¿las declaraciones preparadas realmente mejoran el rendimiento? y http://petesbloggerama.blogspot.com/2007/02/sqlite-adonet-prepared-statements.html ambos parecían indicar que al ejecutar una consulta que se hará varias veces, las declaraciones preparadas son el camino a seguir. También he leído que una declaración preparada es específica para una conexión y que una vez que se cierra la conexión, la declaración preparada se pierde.

Mi confusión es esto. Si abro y cierro mi conexión (lo que puede o no significa que la conexión se cierre debido al grupo de subprocesos), ¿qué tanto uso obtengo de una declaración preparada? Puedo entender que si tengo 1000 objetos, necesito guardar en una sola transacción que la declaración preparada puede ayudar mucho. Sin embargo, no creo que vea un beneficio al guardar un solo objeto en una transacción porque una vez que cierro la conexión, la declaración preparada que se generó a partir del primer objeto ahora se pierde. ¿Es esta una afirmación verdadera?

Mi confusión se ve reforzada por el hecho de que creo que una declaración preparada está vinculada al alcance de mi objeto SQLiteCommand.

Si creo un SQLiteCommand que representa una consulta que ejecutaré a menudo, ¿debo mantener ese SQLiteCommand en memoria para que la declaración preparada permanezca activa?

Si creo un nuevo SQLiteCommand con la misma instrucción SQLite, ¿se reconoce que el nuevo SQLiteCommand es el mismo que el anterior y, por lo tanto, tiene una declaración preparada que se puede usar?

Si mantengo un SQLiteCommand en la memoria y cambio sus parámetros y conexión a medida que abro y cierro la conexión para diferentes transacciones ¿estoy esencialmente manteniendo viva una declaración preparada entre diferentes conexiones?

Lo más probable es que esté pensando demasiado en este punto, pero espero que pueda ayudarme a entender mejor cómo interactúan estas cosas para que pueda obtener el mayor beneficio de ellas.


Es útil recordar que tanto la agrupación de conexiones como las declaraciones preparadas (compiladas) son solo herramientas que tienen sus límites y ningún enfoque puede ser igualmente adecuado para todas las situaciones posibles. Con esto en mente, recordemos cuando uno quiera usar la agrupación de conexiones y las declaraciones preparadas.

Posibles razones para usar la agrupación de conexiones

La agrupación de conexiones es útil cuando las conexiones son caras, por ejemplo:

  • Lleva mucho tiempo establecer una conexión (conexiones de red a un servidor SQL o una base de datos Oracle) y es beneficioso "almacenar en caché" las conexiones abiertas en un intento de mejorar el rendimiento del sistema.
  • Las conexiones son limitadas y se comparten dentro de una aplicación (conexiones desde una aplicación web que atiende múltiples solicitudes simultáneas) o entre aplicaciones, por lo que deben ser liberadas lo antes posible para permitir que los demás clientes continúen.

Posibles razones para usar declaraciones preparadas

Las declaraciones preparadas están destinadas simplemente a mejorar el rendimiento de consultas reutilizables reduciendo el tiempo de análisis.

SQLite: ¿Cuál es la mejor opción?

La respuesta depende de los requisitos de tu aplicación. Personalmente, no estoy seguro de si la agrupación de conexiones SQLite es necesariamente una buena opción. Si su aplicación es de subproceso único, sería mejor usar una única conexión permanente a la base de datos SQLite, que podría ser mucho más rápida que la agrupación y le permitiría también usar declaraciones preparadas. Esto es diferente de SQL Server donde la agrupación de conexiones es un valor predeterminado muy razonable.

Si el rendimiento importa, definitivamente debe perfilar la aplicación para ver si la agrupación de conexiones SQLite es beneficiosa para su escenario.

Preguntás especificas

La mayoría de las respuestas están relacionadas con la source actual del proveedor de System.Data.SQLite .

Si abro y cierro mi conexión (lo que puede o no significa que la conexión se cierre debido al grupo de subprocesos), ¿qué tanto uso obtengo de una declaración preparada?

En general, debe tratar una conexión que sale del grupo como nueva, es decir, no debe esperar obtener ningún beneficio de las declaraciones preparadas previamente. La declaración será "re-preparada" a menos que mantenga el comando y la conexión.

Sin embargo, no creo que vea un beneficio al guardar un solo objeto en una transacción porque una vez que cierro la conexión, la declaración preparada que se generó a partir del primer objeto ahora se pierde. ¿Es esta una afirmación verdadera?

Esta es una declaración verdadera.

Si creo un SQLiteCommand que representa una consulta que ejecutaré a menudo, ¿debo mantener ese SQLiteCommand en memoria para que la declaración preparada permanezca activa?

Sí, necesitas guardarlo. SQLiteCommand contiene una referencia a la declaración preparada.

Si creo un nuevo SQLiteCommand con la misma instrucción SQLite, ¿se reconoce que el nuevo SQLiteCommand es el mismo que el anterior y, por lo tanto, tiene una declaración preparada que se puede usar?

No creo que sea compatible.

Si mantengo un SQLiteCommand en la memoria y cambio sus parámetros y conexión a medida que abro y cierro la conexión para diferentes transacciones ¿estoy esencialmente manteniendo viva una declaración preparada entre diferentes conexiones?

Si cambia la conexión de SQLiteCommand , la declaración será "re-preparada".


No capté exactamente cuál es el problema principal, pero si el problema es cómo insertar declaraciones de inserción masiva en una transacción en tan poco tiempo.

Aquí hay una clase de ayuda que encontré antes que podría ayudarte:

SQLiteBulkInsertHelper.cs

Puedes usarlo así:

SQLiteBulkInsertHelper ContactBlk = new SQLiteBulkInsertHelper("<SQLiteConnection>","<Table Name>"); ContactBlk.AllowBulkInsert = true; ContactBlk.AddParameter("<Column Name>", /*Column Data Type*/System.Data.DbType.Int64); ContactBlk.AddParameter("<Column Name>", /*Column Data Type*/System.Data.DbType.String); ContactBlk.Insert(new object[] {<First Column Value>,<Second Column Value>}); ContactBlk.Flush();

Inténtalo si lo ves como una solución a tu problema.