Я провел много исследований по этой теме, и я согласен со всеми пунктами, упомянутыми в Commonware. Но я думаю, что здесь есть важный момент, которого все здесь упускают. Ответ на этот вопрос полностью зависит от вашего варианта использования, поэтому, если ваше приложение читает базы данных через несколько потоков и только чтение с использованием Singleton имеет огромный удар по производительности поскольку все функции синхронизированы и выполняются последовательно, поскольку существует единственное соединение с базой данных
Кстати, с открытым исходным кодом это здорово. Вы можете копаться прямо в код и посмотреть, что происходит. Из этого и некоторого тестирования я узнал, что верно следующее:
Sqlite takes care of the file level locking. Many threads can read, one can write. The locks prevent more than one writing.
Android implements some java locking in SQLiteDatabase to help keep things straight.
If you go crazy and hammer the database from many threads, your database will (or should) not be corrupted.
Если вы попытаетесь одновременно выполнить запись в базу данных из разных соединений, произойдет сбой. Это не будет ждать, пока первое будет сделано, а затем напишите. Это просто не будет писать ваши изменения. Хуже того, если вы не вызовете нужную версию вставки / обновления в базе данных SQLiteD, вы не получите исключение. Вы просто получите сообщение в LogCat, и это будет оно.
Первая проблема, реальные, четкие связи. Самое замечательное в открытом исходном коде заключается в том, что вы можете копаться прямо и видеть, что происходит. Класс SQLiteOpenHelper делает некоторые забавные вещи. Хотя есть способ получить соединение с базой данных только для чтения, а также соединение для чтения и записи, внутри всегда есть одно и то же соединение. При условии отсутствия ошибок записи в файл, даже соединение только для чтения на самом деле является единственным соединением для чтения и записи. Очень забавно. Таким образом, если вы используете один экземпляр помощника в своем приложении, даже из нескольких потоков, вы никогда не действительно используете несколько соединений.
Кроме того, класс SQLiteDatabase, для которого каждый помощник имеет только один экземпляр, реализует блокировку уровня Java на себе. Таким образом, когда вы на самом деле выполняете операции с базой данных, все другие операции с БД будут заблокированы. Так что, даже если у вас есть несколько потоков, которые делают что-то, если вы делаете это для максимизации производительности базы данных, у меня для вас есть плохие новости. Нет выгоды.
Интересные наблюдения
Если вы отключите один поток записи, так что только один поток записывает в БД, но другое чтение, и оба имеют свои собственные подключения, производительность чтения возрастает ПУТЬ и Я не вижу проблем с блокировкой . Это то, что нужно преследовать. Я еще не пробовал это с пакетной записью.
Если вы собираетесь выполнить более одного обновления любого вида, включите его в транзакцию. Кажется, что 50 обновлений, которые я выполняю в транзакции, занимают столько же времени, сколько 1 обновление за пределами транзакции. Я предполагаю, что вне вызовов транзакций каждое обновление пытается записать изменения БД на диск. Внутри транзакции запись выполняется в одном блоке, а накладные расходы на запись затмевают саму логику обновления.