2012-01-04 5 views
5

iOS 앱에서 SQLite를 사용하고 있으며 사용자가 UI와 상호 작용할 때 저장 /로드 작업이 많습니다. UI가 매우 불안하고 느려지므로 문제입니다.iOS SQLite 성능이 느림

추가 스레드에서 작업을 시도했지만 SQLite에서 가능하지 않다고 생각합니다. 내가 그렇게하면 오류 코드 SQLITE_BUSY와 SQLITE_LOCKED가 자주 발생합니다.

오류 코드가없는 다중 스레드에서이를 수행 할 수있는 방법이 있습니까? 아니면 SQLite를 포기해야합니까?

+1

사용하는 쿼리를 조정하고 쿼리 계획을보고 인덱스가 필요한지 확인해 보았습니까? –

+2

여러 번 쓸 때 트랜잭션을 사용하고 있습니까? 당신은해야합니다 - 그것은 엄청난 차이를 만듭니다. –

+0

Frederick Cheung : 여러 번 쓰기 및 가져 오기를 사용하고 있습니다. 색인 생성이 도움이 될지 살펴 보 겠지만 삽입 할 레코드가 너무 많아 색인 생성이 도움이되지 않는다고 생각합니다. Hot Licks : 여러 번 쓸 때 트랜잭션을 수행하지 않습니다. 동일한 잠금을 사용하여 데이터베이스의 모든 쓰기 작업을 수행해야합니까? – VTS12

답변

0

SQLite를 포기하지 마십시오. 속도가 느려지지 않도록 UI 스레드와 다른 스레드에서이 작업을 수행 할 수 있습니다. 단지 스레드가 데이터베이스를 한 번에 액세스하고 있는지 확인하십시오. 동시 액세스를 처리 할 때 SQLite는 좋지 않습니다.

+1

동시 _reads_에는 문제가 없지만 _updates_는 DB 레벨 잠금보다 복잡한 것의 복잡성 때문에 다른 모든 것을 잠급니다. –

+0

내 문제는 사용자가 데이터에 액세스/기록 할 때 제어 할 수 없다는 것입니다. 예를 들어 하나의보기에서 데이터를 읽고 저장하지만 세부 정보를 클릭하고 데이터 읽기/쓰기를 원하는 새보기를 누를 수 있습니다. 하나의 스레드가 동시에 데이터베이스에 액세스 할 수있는 방법을 확신 할 수 없습니다. – VTS12

3

완벽하게 가능합니다. 백그라운드 스레드에서 SQLite에 대한 액세스를 직렬화하면됩니다.

내 대답은 this recent question에 내 생각에 올바른 방향으로 가리켜 야합니다.

다른 곳에서 언급했듯이 SQLite는 동시 읽기에는 좋지만 쓰기에 대해서는 데이터베이스 수준에서 잠급니다. 즉, 다른 스레드에서 읽고 쓰는 경우 SQLITE_BUSY 및 SQLITE_LOCKED 오류가 발생합니다.

이를 방지하는 가장 기본적인 방법은 디스패치 큐 또는이 액세스는 주 스레드에서 일어나고되지 않기 때문에 1의 동시성이있는 NSOperationQueue에 (읽기 및 쓰기) 중 하나 모든 DB 액세스에는 직렬화하는 것입니다 UI가 영향을받지 않습니다.

이것은 분명히 겹쳐지는 읽기 및 쓰기를 중지하지만 동시 읽기를 중지합니다. 그것이 당신이 취할 수있는 성과에 해당하는지 아닌지는 명확하지 않습니다. 당신이 맞는 볼 그렇다면 그냥 큐에 작업을 추가 할 수 있습니다

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

[backgroundQueue setMaxConcurrentOperationCount:1]; 

: 상기 한 바와 같이

큐를 초기화합니다.

+0

나는 이런 식으로 시도했지만 여전히 오류가 발생했습니다. 이제 디스패치 대기열을 사용하고 있습니다. – VTS12

+0

이제 모든 것이 올바르게 작동합니까? 발송 대기열도 괜찮습니다. – paulbailey

+0

아니요, 디스패치 큐를 사용한 후 계속해서 SQLITE_BUSY 및 SQLITE_LOCKED 오류 코드가 표시됩니다. 또한보기와 같은 이상한 행동이 일찍 터집니다. – VTS12

0

OFF :

당신이 체크 아웃 유무 : FMDB을 그것이 sqlite가 래퍼이며, 스레드 안전합니다. 나는 모든 sqlite 프로젝트에서 그것을 사용했다.

0

sqlite 위에있는 Core Data를 사용하는 것이 좋습니다. 멀티 스레드 환경에서 사용합니다. Concurrency with Core Data에 대한 가이드가 있습니다.

2

모든 것을 전용 SQLite 스레드 또는 한 번에 한 작업 단위로 수행하면 작업이 번거롭므로 특히 지루한 UI를 해결할 수있는 훌륭한 솔루션입니다. 지터에 도움이되지 않을 수도있는 또 다른 기법은 이러한 오류 코드를 찾아내는 것이며, 간단히 반복하여 성공적인 리턴 코드를 얻을 때까지 업데이트를 다시 시도하는 것입니다.

1

WAL 모드로 SQLite를 넣으십시오. 그러면 읽기가 차단되지 않습니다. 그렇게 쓰지는 마십시오. 직렬화해야합니다. 그것을 성취하는 방법은 여러 가지가 있습니다. 그 중 하나가 SQLite에 의해 제공됩니다 - WAL 후크는 다음 쓰기가 시작될 수 있음을 알리는 데 사용될 수 있습니다.

WAL 모드는 일반적으로 앱의 성능을 향상시켜야합니다. 대부분의 것들이 조금 더 빠를 것입니다. 읽기는 전혀 차단되지 않습니다. 큰 트랜잭션 (수 MB) 만 느려집니다. 일반적으로 극적인 것은 없습니다.