Низкая производительность SQLite для iOS - PullRequest
5 голосов
/ 04 января 2012

Я использую SQLite в своем приложении для iOS, и у меня есть много возможностей для сохранения / загрузки, пока пользователь взаимодействует с пользовательским интерфейсом. Это проблема, поскольку она делает интерфейс очень нервным и медленным.

Я пытался выполнить операции в дополнительном потоке, но я не думаю, что это возможно в SQLite. Я получаю коды ошибок SQLITE_BUSY и SQLITE_LOCKED часто, если я делаю это.

Есть ли способ сделать это в многопоточности без этих кодов ошибок, или я должен отказаться от SQLite?

Ответы [ 6 ]

3 голосов
/ 04 января 2012

Это вполне возможно, вам просто нужно сериализовать доступ к SQLite в фоновом потоке.

Мой ответ на этот недавний вопрос должен указать вам правильное направление, я думаю.

Как упоминалось в другом месте, SQLite отлично подходит для одновременного чтения, но блокирует на уровне базы данных для записи. Это означает, что если вы читаете и пишете в разных потоках, вы получите ошибки SQLITE_BUSY и SQLITE_LOCKED.

Самый простой способ избежать этого - сериализовать все доступ к БД (чтение и запись) либо в очереди отправки, либо NSOperationQueue с параллелизмом 1. Поскольку этот доступ не требуется место в основном потоке, ваш пользовательский интерфейс не будет затронут.

Это, очевидно, остановит перекрывающиеся операции чтения и записи, но также остановит одновременные операции чтения. Непонятно, удастся ли это удар по производительности или нет.

Чтобы инициализировать очередь, как описано выше:

NSOperationQueue *backgroundQueue = [[NSOperationQueue alloc] init];

[backgroundQueue setMaxConcurrentOperationCount:1];

Тогда вы можете просто добавлять операции в очередь по своему усмотрению.

2 голосов
/ 04 января 2012

Наличие всего в выделенном потоке SQLite или в очереди операций «одна операция за раз» - отличные решения, особенно для решения вашего нервного пользовательского интерфейса.Другой метод (который может не помочь дрожанию) - определить эти коды ошибок и просто выполнить цикл, повторяя попытку обновления, пока не получите успешный код возврата.

1 голос
/ 03 февраля 2012

Перевести SQLite в режим WAL.Тогда чтение не будет заблокировано.Не так пишет - нужно их сериализовать.Есть разные способы, как этого добиться.Один из них предлагает SQLite - ловушка WAL может использоваться для оповещения о начале следующей записи.

Режим WAL в целом должен повысить производительность вашего приложения.Большинство вещей будет немного быстрее.Чтения не будут заблокированы вообще.Только большие транзакции (несколько МБ) будут тормозить.Вообще ничего драматического.

0 голосов
/ 04 января 2012

Я рекомендую использовать Core Data, который находится поверх sqlite. Я использую его в многопоточной среде. Вот руководство по параллелизму с базовыми данными .

0 голосов
/ 04 января 2012

OFF:

Есть ли у вас заказ: FMDB Это sqlite Wrapper и является потокобезопасным. Я использовал его во всех моих проектах sqlite.

0 голосов
/ 04 января 2012

Не отказывайтесь от SQLite. Вы можете сделать это в потоке, отличном от потока UI , чтобы избежать медлительности. Просто убедитесь, что к базе данных одновременно обращается только один поток один . SQLite не очень хорош при одновременном доступе.

...