Объединение пула соединений SQLite/С# и подготовка к запуску

Я проводил некоторое время, читая различные рекомендации для баз данных и специально для SQLite. Во время чтения я обнаружил, что делаю много вещей, которые мне не следует делать, и когда я пытаюсь исправить эти проблемы, я смутился, когда думал о некоторых более тонких деталях использования SQLite с его реализацией ADO.

Моя путаница проистекает из подготовленных заявлений и пула соединений.

При чтении http://msdn.microsoft.com/en-us/library/ms971481.aspx я обнаружил, что соединения должны открываться только для транзакции. После завершения транзакции соединение должно быть закрыто. У меня нет четкого понимания того, почему это так, но я работал над предположением, что автор (-ы) лучше знает меня. Я понимаю, что когда соединение закрыто, это не значит, что оно действительно были закрыты. Это просто означает, что он был возвращен в пул.

Теперь, чтобы улучшить мои запросы и вставки, я прочитал об использовании подготовленных операторов. В SQLite, действительно ли подготовленные операторы действительно улучшают производительность? и http://petesbloggerama.blogspot.com/2007/02/sqlite-adonet-prepared-statements.html оба казались чтобы указать, что при выполнении запроса, который будет выполняться несколько раз, готовые заявления - это путь. Я также прочитал, что подготовленный оператор относится к соединению и что после закрытия соединения готовый оператор теряется.

Мое замешательство таково. Если я открываю и закрываю мое соединение (которое может или не означает, что соединение закрывается из-за пула потоков), то сколько я использую из подготовленного заявления? Я могу понять, что если у меня есть 1000 объектов, мне нужно сохранить в одной транзакции, что подготовленный оператор может многое помочь. Однако я не считаю, что я выиграю от сохранения одного объекта в транзакции, потому что, как только я закрою соединение, готовый оператор, который был сгенерирован первым объектом, теперь потерян. Это истинное утверждение?

Моему путанице способствует тот факт, что я считаю, что подготовленный оператор связан с областью моего объекта SQLiteCommand.

Если я создаю SQLiteCommand, который представляет собой запрос, который я буду выполнять часто, мне нужно сохранить этот SQLiteCommand в памяти, чтобы подготовленный оператор оставался активным?

Если я создаю новый SQLiteCommand с тем же оператором SQLite, то признается, что новый SQLiteCommand совпадает с предыдущим и, следовательно, имеет подготовленный оператор, который можно использовать?

Если я сохраняю SQLiteCommand в памяти и изменяю его параметры и соединение, когда я открываю и закрываю соединение для разных транзакций, я по существу сохраняю подготовленный оператор между различными соединениями?

Скорее всего, я думаю о мыслях на этом этапе, но надеюсь, что вы поможете мне лучше понять, как эти вещи взаимодействуют, чтобы я мог извлечь максимальную выгоду из них.

Ответ 1

Это помогает помнить, что оба пула соединений и подготовленные (скомпилированные) операторы - это просто инструменты, которые имеют свои пределы, и ни один подход не может быть одинаково подходящим для всех возможных ситуаций. Помня об этом, помните, когда можно было бы использовать пул соединений и подготовленные операторы.

Возможные причины использования пула соединений

Пул соединений полезен, когда соединения дороги, например:

  • Требуется значительное время для установления соединения (сетевые подключения к SQL Server или Oracle DB), и полезно "кэшировать" открытые соединения, пытаясь улучшить производительность системы.
  • Соединения ограничены и совместно используются в приложении (соединения из веб-приложения, обслуживающего несколько одновременных запросов) или между приложениями, поэтому их необходимо как можно скорее освободить, чтобы остальные клиенты продолжали.

Возможные причины использования подготовленных заявлений

Подготовленные утверждения просто предназначены для повышения производительности повторно используемых запросов путем сокращения времени синтаксического анализа.

SQLite: какой лучший выбор?

Ответ зависит от ваших требований приложения. Лично я не уверен, что объединение соединений SQLite обязательно является хорошим выбором. Если ваше приложение однопоточное, лучше всего использовать одно постоянное соединение с SQLite DB, которое может быть намного быстрее, чем объединение, и позволит вам также использовать подготовленные заявления. Это отличается от SQL Server, когда пул соединений является очень разумным по умолчанию.

Если производительность имеет значение, вам обязательно нужно профилировать приложение, чтобы узнать, полезен ли пул соединений SQLite для вашего сценария.

Конкретные вопросы

Большинство ответов связаны с текущим System.Data.SQLite провайдером source.

Если я открываю и закрываю свое соединение (что может означать или не означать соединение закрывается из-за пула потоков), то сколько Я действительно получаю от подготовленного заявления?

Как правило, вы должны рассматривать соединение, выходящее из пула, как новое, то есть вы не должны рассчитывать получить какую-либо выгоду от заявлений, подготовленных ранее. Заявление будет "повторно подготовлено", если вы не сохраните команду и соединение.

Однако я не верю, что увижу выгоду от сохранения одного объект в транзакции, потому что, как только я закрою соединение, подготовленный оператор, который был сгенерирован первым объектом, теперь потерял. Это истинное утверждение?

Это истинное утверждение.

Если я создаю SQLiteCommand, который представляет запрос, который я буду часто выполняя, мне нужно сохранить этот SQLiteCommand в памяти для подготовленное выражение, чтобы оставаться активным?

Да, вам нужно сохранить его. SQLiteCommand содержит ссылку на подготовленный оператор.

Если я создаю новый SQLiteCommand с тем же оператором SQLite, это что новый SQLiteCommand совпадает с предыдущим и таким образом, имеет подготовленный оператор, который можно использовать?

Я не думаю, что он поддерживается.

Если я сохраню SQLiteCommand в памяти и изменю его параметры и когда я открываю и закрываю соединение для разных Я по существу сохраняю подготовленное выражение между различными соединениями?

Если вы измените соединение SQLiteCommand, оператор будет "повторно подготовлен".

Ответ 2

Я не понял точно, что является основной проблемой, но если проблема заключается в том, как вставлять операторы объемной вставки в одну транзакцию за столь короткое время.

Вот вспомогательный класс, который я нашел ранее, который может вам помочь:

SQLiteBulkInsertHelper.cs

Вы можете использовать его следующим образом:

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();

Попробуйте, если вы рассматриваете это как решение своей проблемы.