Оптимизация выбора с транзакцией в SQLite 3

Я читал, что обтекание большого количества SELECT в BEGIN TRANSACTION/COMMIT было интересной оптимизацией.

Но действительно ли эти команды необходимы, если я использую "PRAGMA journal_mode = OFF" раньше? (Что, если я помню, отключает журнал и, очевидно, систему транзакций тоже.)

Ответы

Ответ 1

"Использовать транзакции - даже если вы просто читаете данные. Это может привести к нескольким миллисекундам".

Я не уверен, где этот блог Katashrophos.net получает эту информацию, но обертывание операторов SELECT в транзакции ничего не делает. Транзакции всегда используются и используются только при внесении изменений в базу данных, и транзакции нельзя отключить. Это требование. Многие не понимают, что если вы вручную не выполняете транзакции BEGIN и COMMIT, каждый оператор будет автоматически помещен в свою собственную уникальную транзакцию. Обязательно прочитайте де-факто SO вопрос об улучшении производительности sqlite. То, что автор блога, возможно, пыталось сказать, заключается в том, что если вы планируете сделать INSERT, затем SELECT, затем еще один INSERT, то это увеличит производительность, чтобы вручную обернуть эти операторы в один сделка. В противном случае sqlite автоматически поместит два оператора insert в отдельные уникальные транзакции.

В соответствии с "SQL as Understood by SQLite" документация, касающаяся транзакций:
"Никакие изменения не могут быть внесены в базу данных, кроме как внутри транзакции. Любая команда, которая изменяет базу данных (в основном, любую команду SQL, отличную от SELECT), автоматически запустит транзакцию, если она еще не действует".

Наконец, отключение ведения журнала через PRAGMA journal_mode = OFF не отключает транзакции, а только протоколирование. Но отключение журнала - хороший способ повысить производительность. Обычно после каждой транзакции sqlite регистрирует транзакцию в журнале. Когда это не нужно делать, вы получаете повышение производительности.

UPDATE:
Поэтому мне было доведено до сведения "элегантных кубиков", что выражение о документации SQLite, приведенное выше, вводит в заблуждение. Операторы SELECT фактически используют транзакционную систему. Это используется для получения и освобождения блокировки SHARED в базе данных. В результате, более эффективно переносить несколько операторов SELECT в одну транзакцию. Таким образом, блокировка только приобретается и освобождается один раз, а не для каждого отдельного оператора SELECT. Это становится немного более эффективным, а также гарантируя, что все операторы SELECT будут обращаться к одной и той же версии базы данных в случае, если что-то было добавлено/удалено какой-либо другой программой.

Ответ 2

Обратите внимание, что я не согласен с BigMacAttack.

Для SQLITE обертывание SELECT в транзакции делает что-то: Это уменьшает количество замков SHARED, которые были получены и затем опущены.

Ссылка: http://www.mail-archive.com/sqlite-users%40sqlite.org/msg79839.html

Итак, я думаю, что транзакция также была бы полезной, даже если бы вы отключили функцию journal_mode, потому что все еще есть накладные расходы на блокировку.

Может быть, read_uncommitted - это то, что вы могли бы подумать - я бы предположил, что он отключит блокировку SHARED.