ios - 미러링 - sql mirroring requirements



JSON을 통해 서버 데이터베이스를 클라이언트 데이터베이스로 미러링하는 프로세스를 개선 하시겠습니까? (5)

  1. 테이블의 각 행마다 타임 스탬프 열이 있어야합니다. 하나도 없으면 추가해야합니다.
  2. 처음으로 데이터베이스 덤프를 가져올 때마다 마지막 업데이트 날짜와 시간을 저장합니다.
  3. 다음 번에 매번 이전 다운로드 작업 이후에 변경되거나 업데이트 된 레코드 만 반환하도록 데이터베이스에 지시합니다. 사라진 레코드를 제거하기위한 "삭제 된"플래그도 있어야합니다.
  4. 그런 다음 모든 일치하는 시간을 절약 하는 특정 일치 레코드업데이트 하면됩니다.

처음으로 동기화 속도를 높이기 위해 앱을 사용하여 시드 데이터베이스를 제공 할 수 있으므로 네트워크 작업없이 즉시 가져올 수 있습니다.

  1. JSON 파일을 직접 다운로드하십시오.
  2. 프로젝트에 넣으십시오.
  3. 프로젝트 구성이나 헤더 파일의 어딘가에서 다운로드 날짜와 시간을 기록합니다.
  4. 첫 번째 실행에서 파일을 찾아서로드 한 다음 업데이트하는 것처럼 진행하십시오.
  5. 의심스러운 경우 매뉴얼을 참조하십시오.

예:

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"cities" 
                                            ofType:@"json"];
NSData *citiesData = [NSData dataWithContentsOfFile:filePath];
// I assume that you're loading an array
NSArray *citiesSeed = [NSJSONSerialization JSONObjectWithData:citiesData 
                       options:NSJSONReadingMutableContainers error:nil];

나는 리팩터링 할 필요가있는 준비된 엔터프라이즈 (비 AppStore) 레거시 IOS 애플리케이션을 가지고있다. (그것은 다른 개발자에 의해 작성되었으며 현재 나의 직무에 대한 전임자였다.)

이 응용 프로그램은 MSSQL 데이터베이스가있는 서버에서 JSON을 통해 데이터를 가져옵니다. 데이터베이스 스키마는 약 30 개의 테이블을 가지고 있으며, 클라이언트, 도시, 에이전시 각각 각각 약 10.000 개의 레코드가 있으며 앞으로 더 많은 성장이 예상됩니다. JSON이 수신되면 (각 테이블에 대해 하나의 JSON 요청 및 응답 쌍) - CoreData에 매핑됩니다.이 프로세스는 해당 CoreData 엔터티 (클라이언트, 도시, 에이전시 및 기타)를 함께 결합합니다. 즉 CoreData 레이어에서 이러한 엔티티간에 관계를 설정합니다.

자체적으로 프로젝트의 CoreData 가져 오기 부분 (또는 읽기 부분)은 많이 최적화되어 있습니다. CoreData가 가지고있는 거의 모든 가능한 성능과 메모리를 사용하기 때문에 응용 프로그램의 UI 레이어가 매우 빠르고 반응성이 높은 이유가됩니다. 그 일을 완전히 만족스럽고 적절하다고 생각하십시오.

문제 는 CoreData 레이어 준비 과정, 즉 서버 대 클라이언트 동기화 프로세스입니다. 너무 많은 시간이 걸립니다. 30 개의 네트워크 요청을 고려하여 30 개의 JSON 팩 ( "팩"은 "하나의 테이블 - 하나의 JSON"을 의미 함)을 작성한 다음 30 개의 CoreData 엔티티에 매핑 한 다음 서로 붙입니다 (적절한 CoreData 관계가 설정 됨). 이 프로젝트에서이 모든 일이 어떻게 이루어지는 지 처음 보았을 때 (너무 느림), 내 머리 속으로 들어가는 첫 번째 아이디어는 다음과 같습니다.

"처음으로 전체 동기화가 수행되었습니다 (응용 프로그램의 첫 번째 실행 시간). 예를 들어 하나의 아카이브 된 파일 (데이터베이스 덤프와 같은)에서 전체 데이터베이스 데이터를 가져 와서 전체적으로 코어 데이터로 가져옵니다 나라".

그러나 그런 한 파일 덤프의 전송이 가능했다 할지라도 CoreData는 해당 CoreData 엔터티의 접착을 수행하여 적절한 관계를 설정해야하므로 내가 할 수 있다고 상상하기 어렵다는 것을 깨달았습니다. 이 계획에 의존한다면 성능면에서 이점이 있습니다.

또한 제 동료는 SQLite를 Core Data의 완전한 대안으로 생각하라고 제안했지만 불행히도이 도구를 사용 해본 경험이 없기 때문에 심각한 디자인 결정의 모든 결과를 예견하는 것이 완전히 눈이 멀었습니다 (심지어 동기화 프로세스가 매우 느리며, 내 앱 이 작동합니다 . 특히 UI 성능이 매우 좋습니다.) SQLite에 대해 상상할 수있는 유일한 것은 코어 데이터와 달리 클라이언트 측에서 몇 가지 추가적인 릴레이션을 붙이도록 강요하지 않을 것입니다. SQLite는 좋은 외래 키 시스템을 가지고 있기 때문입니다.

그래서 여기에 질문이 있습니다 (응답자는 응답 할 때이 점들을 섞지 마십시오. 나는 그들 모두에 대해 너무 혼란 스럽습니다).

  1. 누구나 위에서 설명한 방식으로 "전체 데이터베이스를 처음으로 대량으로 가져 오는"경험을 한 사람이 있습니까? JSON <-> CoreData 쌍을 악용해야하는지에 대해 알고 있으면 매우 감사 할 것입니다.

  2. Core Data는 30 개의 엔티티에 대한 대응 관계를 설정할 필요없이 해당 30 테이블 스키마 (위에서 설명한 "30 팩의 JSON"이외의 특정 소스를 사용)를 대량으로 생성 할 수있는 일부 전역 가져 오기 메커니즘이 있습니까?

  3. 2) 불가능할 경우 동기화 프로세스 속도를 높일 수 있습니까? 여기에 내 응용 프로그램에서 사용하는 현재 JSON <-> CoreData 스키마의 개선이 필요합니다.

  4. SQLite로 마이그레이션 : 이러한 마이그레이션을 고려해야합니까? 나는 그것으로부터 무엇을 얻을 것인가? 어떻게 복제 -> 전송 -> 클라이언트 준비 의 전체 프로세스는 다음과 같이 보일 수 있습니까?

  5. CoreData 및 SQLite에 대한 다른 대안 - 어떤 모양 일 수 있습니까?

  6. 내가 묘사 한 상황에 대한 다른 생각이나 비전이 있습니까?

업데이트 1

Mundi가 작성한 대답은 훌륭하지만 (하나의 큰 JSON, SQLite 사용을위한 "아니오"), 내가 설명한 문제에 대한 다른 통찰력이 있다면 나는 여전히 관심이있다.

업데이트 2

나는 러시아어로 나의 질문에 대한 희망으로 나의 상황을 묘사 할 수있는 최선의 방법을 사용하여 그것을 읽는 모든 사람들에게 분명하게 될 수 있었다. 이 두번째 업데이트로 나는 나의 질문을 더욱 분명하게하기 위해 좀 더 많은 안내서를 제공하려고 노력할 것이다.

두 가지 이분법을 고려하십시오.

  1. iOS 클라이언트에서 CoreData와 SQLite의 데이터 레이어로 사용할 수있는 항목은 무엇입니까?
  2. 전송 레이어로 사용할 수있는 것은 무엇입니까? - JSON (응답시 제안 된대로 단일 JSON 일 수도 있음) 또는 일부 DB 자체 덤프 (물론 가능할 수도 있습니다. 또한 내 질문에 이것을 요구).

나는이 두 가지 이분법의 교차점에 의해 형성되는 "섹터"라고 생각합니다. 첫 번째 것에서 CoreData를 선택하고 두 번째에서 JSON은 iOS 개발 세계에서 가장 널리 퍼진 기본값이며 또한 내 응용 프로그램에서 사용됩니다 이 질문에서.

그 말을 들으면 CoreData-JSON 쌍에 대한 답변과 다른 "섹터"(SQLite 및 일부 덤프 방식을 선택하는 이유는 무엇입니까?)에 대한 답변을 보게되어 감사하다고 말합니다.

또한 주목해야 할 중요한 점은 다른 대안에 대한 현재 옵션을 삭제하지 않고 단지 동기화 및 UI 단계에서 빠르게 작동하도록하려는 것입니다. 그래서 현재 계획을 개선하는 것에 대한 답변과 다른 계획을 제안하는 답변을 환영합니다!

이제 현재 CoreData-JSON 상황에 대한 자세한 정보를 제공하는 다음 업데이트 # 3을 참조하십시오.

업데이트 3

말했듯이, 현재 내 애플 리케이션은 JSON 30 팩 - 전체 테이블에 대해 하나의 팩을받습니다. 예를 들어 클라이언트, 대행사, 도시 등의 대용량 테이블을 살펴 보겠습니다.

그것은 코어 데이터이므로 client 레코드에 비어 있지 않은 agency_id 필드가있는 경우 Agency (NSManagedObject subclass) 클래스의 새 Core Data 엔터티를 agency_id 레코드의 JSON 데이터로 채워야합니다. 그래서 이미 해당 코어가 있어야합니다 클래스 에이 기관 Agency (NSManagedObject's subclass) 대한 데이터 엔터티, 그리고 마지막으로 나는 client.agency = agency; 와 같은 것을 할 필요가있다 client.agency = agency; [currentManagedObjectContext save:&error] 를 호출하십시오. 이렇게하면 나중에이 클라이언트에 가져와서 해당 엔티티를 찾을 수있는 .agency 속성을 요청할 수 있습니다. 이런 식으로 할 때 나는 완전히 제정신이되기를 바랍니다.

이제이 패턴이 다음 상황에 적용된다고 상상해보십시오.

나는 10000 개의 클라이언트와 4000 개의 도시와 6000 개의 에이전시 (클라이언트는 하나의 도시를 가지고 도시는 많은 클라이언트를 가지고 클라이언트는 에이전시를 가지고 있고, 에이전시는 많은 클라이언트를 가지고 있고, 에이전시는 하나의 도시를 가지고 있고, 도시는 많은 에이전시를 가지고있다.

이제 핵심 데이터 수준에서 다음 관계를 설정하려고합니다. 클라이언트 엔터티 client 가 해당 도시와 해당 기관에 연결되기를 원합니다.

이 프로젝트의 현재 구현은 매우 못 생겼습니다.

  1. 종속성 순서는 다음과 같습니다. City -> Agency -> Client 즉 City가 먼저 구워 져야 할 필요가있는 응용 프로그램은 City에 대한 엔터티 만들기를 시작하고이를 Core Data에 유지합니다.

  2. 그런 다음 모든 JSON 레코드를 반복합니다. 모든 대행사는 새로운 엔티티 agency 만들고 city_id 는 해당 엔티티 city 가져오고 agency.city = city 사용하여 연결합니다. 전체 대행사 JSON 배열을 반복 한 후에 현재 관리 객체 컨텍스트가 저장됩니다 (실제로 [managedObjectContext save :]는 500 개의 레코드가 처리 된 후 여러 번 수행됩니다). 이 단계에서 6000 개 에이전시마다 모든 클라이언트에 대해 4000 개의 도시 중 하나를 가져 오는 것이 전체 동기화 프로세스에 큰 성능 영향을 미친다는 것은 분명합니다.

  3. 그런 다음 마침내 클라이언트의 JSON을 처리합니다. 이전 2 단계와 마찬가지로 10000 개의 JSON 배열 전체를 반복하고 해당 기관 및 ZOMG 도시를 하나씩 가져 와서 전체적인 성능에 영향을줍니다 이전 단계 2와 같은 방식입니다.

그것은 모두 아주 나쁜 것입니다.

여기서 볼 수있는 유일한 성능 최적화는 첫 번째 단계에서는 도시 ID (실제 ID의 NSNumber를 의미 함)와 City 항목을 값으로 오류가있는 큰 사전을 남길 수 있으므로 다음과 같은 과정을 추악하게 찾는 것을 방지 할 수 있습니다 2 단계를 수행 한 다음 3 단계에서 비슷한 캐싱 트릭을 사용하여 동일한 작업을 수행하지만 문제는 [고객 - 도시, 고객 - 대행사, 대행사 - 도시]와 같이 훨씬 더 많은 관계가 있다는 것입니다. 모든 엔티티의 캐싱을 포함하는 최종 절차는 iPad 장치가 내 앱을 예약 할 수있는 자원에 가장 많이 부딪 힐 수 있습니다.

업데이트 4

미래의 응답자를위한 메시지 : 나는이 답변을 자세하고 잘 형성하기 위해 최선을 다 했으므로 자세한 대답으로 답할 것을 기대합니다. 귀하의 대답이 여기에서 논의 된 문제의 복잡성을 실제로 해결하고 내 질문을 가능한 한 많이 명확하게하기 위해 내 노력을 보완하면 좋을 것입니다. 감사.

업데이트 5

관련 항목 : 서버의 데이터를 캐시하는 클라이언트의 코어 데이터 (iOS) 전략 , RestKit으로 POST 요청을 만들고 코어 데이터에 응답을 매핑하려고합니다 .

업데이트 6

새로운 현상금을 여는 것이 더 이상 가능하지 않고 대답이 받아 들여지더라도,이 주제에 관한 추가 정보가 포함 된 다른 답변을 볼 수있어서 기쁩니다. 미리 감사드립니다.


Answer #1

나는 내 상황에 유용한 기술과 조언을 요약 한 내 대답을 쓰기로 결정했습니다. 답변을 게시 한 모든 사람들에게 감사드립니다.

I. 운송

  1. "하나의 JSON". 이것은 내가 시도하고 싶다는 생각이다. @ mundi 감사 합니다 .

  2. JSON을 하나의 JSON 팩 또는 30 개의 별도 'one table - one pack'으로 클라이언트에 보내기 전에 JSON을 보관하는 아이디어.

II. 핵심 데이터 관계 설정

한 가지 방법으로 수행 된 것처럼 가상의 대량 가져 오기 작업을 사용하여 JSON-> CoreData 가져 오기 프로세스를 설명합니다 (확실하지는 않습니다 - 아마 논리적 인 청크로 분할 할 것입니다).

내 상상의 응용 프로그램에서 상상해 보자. "대용량"은 "한 번에 메모리에 보관할 수없고 일괄 처리를 사용하여 가져와야 함"을 의미하는 15 개의 대용량 테이블과 각각이 500 개 미만인 15 개의 대용량 테이블을 상상해 봅시다.

널찍한:

  • 도시 (15k +)
  • 고객 (30k +)
  • 사용자 (15k +)
  • 이벤트 (5k +)
  • 액션 (2k +) ...

작은:

  • client_types (20-)
  • visit_types (10-)
  • 직책 (10-) ...

상상해 봅시다. 이미 JSON 팩을 다운로드하여 복합 NSArray / NSDictionary 변수로 파싱했습니다. citiesJSON, clientsJSON, usersJSON ...이 있습니다.

1. 먼저 작은 테이블 작업

내 의사 메서드는 작은 테이블을 먼저 가져 오는 것으로 시작됩니다. client_types 테이블을 가져와 봅시다. clientTypesJSON 반복하고 ClientType 객체 (NSManagedObject의 하위 클래스)를 만듭니다. 그보다 나는이 객체들을 값으로 사용하는 사전에 결과 객체를 수집하고 이들 객체의 "ids"(외래 키)를 키로 수집합니다.

다음은 의사 코드입니다.

NSMutableDictionary *clientTypesIdsAndClientTypes = [NSMutableDictionary dictionary];
for (NSDictionary *clientTypeJSON in clientsJSON) {
    ClientType *clientType = [NSEntityDescription insertNewObjectForEntityForName:@"ClientType" inManagedObjectContext:managedObjectContext];

    // fill the properties of clientType from clientTypeJSON

    // Write prepared clientType to a cache
    [clientTypesIdsAndClientTypes setValue:clientType forKey:clientType.id];
}

// Persist all clientTypes to a store.
NSArray *clientTypes = [clientTypesIdsAndClientTypes allValues];
[managedObjectContext obtainPermanentIDsForObjects:clientTypes error:...];

// Un-fault (unload from RAM) all the records in the cache - because we don't need them in memory anymore.
for (ClientType *clientType in clientTypes) {
    [managedObjectContext refreshObject:clientType mergeChanges:NO];
}

결과적으로 작은 테이블을 사전으로 묶어서 각각에 해당하는 객체 세트와 ID를 갖게됩니다. 우리는 나중에 그것들의 값 (NSManagedObjects)이 오류이기 때문에 나중에 다시 패치하지 않고 사용하게 될 것입니다.

2. 1 단계에서 얻은 작은 테이블의 오브젝트에 대한 캐시 사전을 사용하여 관계를 설정하십시오

복잡한 테이블 clients 고려해 봅시다. 우리는 clientsJSON 을 가지고 clientsJSON 각 클라이언트 레코드에 대해 clientType 관계를 설정해야합니다. clientTypes 와 해당 ID가있는 캐시가 있기 때문에 쉽습니다.

for (NSDictionary *clientJSON in clientsJSON) {
    Client *client = [NSEntityDescription insertNewObjectForEntityForName:@"Client" inManagedObjectContext:managedObjectContext];

    // Setting up SQLite field 
    client.client_type_id = clientJSON[@"client_type_id"];

    // Setting up Core Data relationship beetween client and clientType
    client.clientType = clientTypesIdsAndClientTypes[client.client_type_id];
}

// Save and persist

3. 큰 테이블 다루기 - 일괄 처리

30k + 클라이언트를 보유한 대형 클라이언트 clientsJSON 을 생각해 봅시다. 우리는 전체 clientsJSON 반복하지 않고 적당한 크기 (500 레코드)의 덩어리로 분할하여 [managedObjectContext save:...] 가 500 레코드마다 호출되도록합니다. 또한 각 500 레코드 배치의 작업을 @autoreleasepool block 으로 래핑하는 것이 중요합니다. - 핵심 데이터 성능 오버 헤드 감소 성능 가이드

주의하십시오 - 4 단계는 전체 clientsJSON 아닌 500 레코드의 배치에 적용된 작업을 설명합니다!

4. 큰 테이블 다루기 - 큰 테이블과의 관계 설정하기

다음과 같은 방법을 고려해보십시오. 잠시 후에 사용하겠습니다.

@implementation NSManagedObject (Extensions)
+ (NSDictionary *)dictionaryOfExistingObjectsByIds:(NSArray *)objectIds inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext {
    NSDictionary *dictionaryOfObjects;

    NSArray *sortedObjectIds = [objectIds sortedArrayUsingSelector:@selector(compare:)];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:NSStringFromClass(self)];

    fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(id IN %@)", sortedObjectIds];
    fetchRequest.sortDescriptors = @[[[NSSortDescriptor alloc] initWithKey: @"id" ascending:YES]];

    fetchRequest.includesPropertyValues = NO;
    fetchRequest.returnsObjectsAsFaults = YES;

    NSError *error;
    NSArray *fetchResult = [managedObjectContext executeFetchRequest:fetchRequest error:&error];

    dictionaryOfObjects = [NSMutableDictionary dictionaryWithObjects:fetchResult forKeys:sortedObjectIds];

    return dictionaryOfObjects;
}
@end

Client 를 저장해야하는 일괄 (500) 개의 Client 레코드가 포함 된 Client 팩을 고려해 보겠습니다. 또한 우리는 이들 고객과 그들의 대행사 사이에 관계를 설정해야합니다 ( Agency , 외래 키는 agency_id ).

NSMutableArray *agenciesIds = [NSMutableArray array];
NSMutableArray *clients = [NSMutableArray array];

for (NSDictionary *clientJSON in clientsJSON) {
    Client *client = [NSEntityDescription insertNewObjectForEntityForName:@"Client" inManagedObjectContext:managedObjectContext];

    // fill client fields...

    // Also collect agencies ids
    if ([agenciesIds containsObject:client.agency_id] == NO) {
        [agenciesIds addObject:client.agency_id];
    }        

    [clients addObject:client];
}

NSDictionary *agenciesIdsAndAgenciesObjects = [Agency dictionaryOfExistingObjectsByIds:agenciesIds];

// Setting up Core Data relationship beetween Client and Agency
for (Client *client in clients) {
    client.agency = agenciesIdsAndAgenciesObjects[client.agency_id];
}

// Persist all Clients to a store.
[managedObjectContext obtainPermanentIDsForObjects:clients error:...];

// Un-fault all the records in the cache - because we don't need them in memory anymore.
for (Client *client in clients) {
    [managedObjectContext refreshObject:client mergeChanges:NO];
}

여기에서 사용하는 대부분의 내용은 Apple 가이드에서 설명합니다 : 핵심 데이터 성능 , 효율적으로 데이터 가져 오기 . 따라서 1 ~ 4 단계의 요약은 다음과 같습니다.

  1. 객체가 지속될 때 객체를 오류로 변환하므로 임포트 작업이 더 진행될 때 객체의 속성 값이 불필요하게됩니다.

  2. 개체를 값으로 사용하고 해당 ids 를 키로 사용하여 사전을 구성하십시오. 따라서 이러한 사전은 이러한 개체와 다른 개체 사이에 관계를 구성 할 때 조회 테이블 역할을 할 수 있습니다.

  3. 많은 수의 레코드를 반복 할 때 @autoreleasepool을 사용하십시오.

  4. dictionaryOfExistingObjectsByIds 와 유사한 메소드를 사용하거나 Tom이 그의 대답에서 참조하는 메소드 인 효율적인 데이터 임포트 ( SQL IN 술어가있는 메소드)를 사용하여 많은 수의 인출을 줄입니다. Tom의 답변을 읽고 Apple의 해당 가이드를 참조하여이 기술을 더 잘 이해하십시오.

이 주제에 대한 좋은 읽을 거리

objc.io 문제 # 4 : 대형 데이터 세트 가져 오기


Answer #2

서버를 제어 할 수 있습니까? 나는 당신이 다음 단락에서하는 것처럼 들리므로 묻습니다.

"처음으로 전체 동기화가 수행되었습니다 (응용 프로그램의 첫 번째 실행 시간). 예를 들어 하나의 아카이브 된 파일 (데이터베이스 덤프와 같은)에서 전체 데이터베이스 데이터의 가져 오기를 수행 한 다음 어떻게 든 전체를 CoreData 토지로 가져옵니다 ".

덤프를 보낼 수 있다면 코어 데이터 파일 자체를 보내지 않는 이유는 무엇입니까? 핵심 데이터 (기본적으로)는 SQLite 데이터베이스를 기반으로합니다. 서버에서 데이터베이스를 생성하고 압축하여 전선을 통해 전송해야하는 이유는 무엇입니까?

이는 모든 JSON 구문 분석, 네트워크 요청 등을 제거하고 간단한 파일 다운로드 및 아카이브 추출으로 대체 할 수 있음을 의미합니다. 우리는이 프로젝트를 통해 성과를 극적으로 향상 시켰습니다.


Answer #3

여기에 내 권고 사항이 있습니다.

  • magicalrecord 사용하십시오. 그것은 당신에게 많은 상용어 코드를 저장하는 CoreData 래퍼입니다. 플러스 매우 흥미로운 기능이 있습니다.
  • 다른 제안대로 한 요청에서 모든 JSON을 다운로드하십시오. 첫 번째 JSON 문서를 앱에 포함 할 수 있다면 앱을 처음 열 때 다운로드 시간을 저장하고 데이터베이스를 채우기 시작할 수 있습니다. 또한, magicalrecord를 사용하면 별도의 스레드에서이 저장 작업을 수행 한 다음 모든 컨텍스트를 자동으로 동기화하는 것이 매우 쉽습니다. 이렇게하면 앱의 응답 속도를 향상시킬 수 있습니다.
  • 첫 번째 수입 문제를 해결 한 후에는 추악한 방법을 리펙토링해야 할 것 같습니다. 다시 말하지만 magicalrecord를 사용하여 쉽게 해당 엔티티를 만들 것을 제안합니다.

Answer #4

최근에 상당히 큰 프로젝트를 Core Data에서 SQLite로 옮겼습니다. 그 주된 이유 중 하나는 대량 삽입 성능이었습니다. 우리가 전환에서 잃어버린 몇 가지 기능이 있었는데, 당신이 그것을 피할 수 있다면 전환을 할 것을 권하지는 않습니다. SQLite로 전환 한 후에는 코어 데이터가 투명하게 처리하는 대량 삽입 이외의 영역에서 성능 문제가 발생했습니다. 이러한 새로운 문제가 수정되었지만 백업 및 실행에 다소 시간이 걸렸습니다. Core Data에서 SQLite로 전환하는 데 시간과 노력을 들였지만 후회가 없다고 말할 수는 없습니다.

그걸 정리하자면 대량 삽입 성능을 수정하기 전에 몇 가지 기본 측정 값을 얻으시기 바랍니다.

  1. 현재 상태에서 레코드를 삽입하는 데 걸리는 시간을 측정합니다.
  2. 이러한 개체 간의 관계 설정을 건너 뛰고 삽입 성능을 측정하십시오.
  3. 간단한 SQLite 데이터베이스를 만들고 그로 인서트 성능을 측정하십시오. 이렇게하면 실제 SQL 삽입을 수행하는 데 걸리는 시간을 매우 정확하게 예측할 수있을뿐만 아니라 핵심 데이터 오버 헤드에 대한 좋은 아이디어를 얻을 수 있습니다.

삽입을 가속화하기 위해 박쥐를 시도 할 수있는 몇 가지 사항은 다음과 같습니다.

  1. 대량 삽입을 수행 할 때 활성 가져온 결과 컨트롤러가 없는지 확인하십시오. 액티브 (active) 란, Null이 아닌 대리자가있는 결과 컨트롤러를 가져온 것을 의미합니다. 필자의 경험에 따르면 대량 삽입을 시도 할 때 Core Data의 변경 추적은 가장 비용이 많이 드는 단일 작업이었습니다.
  2. 단일 컨텍스트에서 모든 변경을 수행하고 대량 삽입이 완료 될 때까지 다른 컨텍스트의 변경 사항 병합을 중지합니다.

실제 상황을 자세히 파악하려면 Core Data SQL 디버깅을 활성화하고 실행중인 SQL 쿼리를 확인하십시오. 이상적으로는 많은 INSERT와 몇 가지 UPDATE를보고 싶을 것이다. 그러나 너무 많은 SELECT 및 / 또는 UPDATE를 발견하면 너무 많이 읽거나 객체를 업데이트하고 있다는 신호입니다.

Core-Data 프로파일 러 도구를 사용하여 Core Data로 진행되는 작업에 대한 더 높은 수준의 개요를 얻으십시오.





core-data