7

SO에서 검색했지만 관계를 처리 할 때 핵심 데이터에서 관리 대상 개체를 삭제할 때 성능을 향상시킬 제안을 찾지 못했습니다.코어 데이터에서 계단식 규칙을 사용하여 관리 대상 개체를 삭제할 때의 성능 고려 사항

시나리오는 매우 간단합니다. enter image description here

세 가지 엔티티가 있습니다. 각 개체는 다음 개체와 연결됩니다. 예를 들어, FirstLevelsecondLevels부터 SecondLevel까지의 관계를가집니다. FirstLevel에서 SecondLevel까지의 삭제 규칙은 SecondLevel에서 FirstLevel까지 삭제 규칙이 인 Nullify 인 동안이면 계단식입니다. 동일한 규칙이 SecondLevelThirdLevel 사이에 적용됩니다. 나는 전체 그래프를 삭제할 때

, 나는 다음과 같은 방법을 수행 :

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription entityForName:@"FirstLevel" inManagedObjectContext:context]; 
[fetchRequest setEntity:entity]; 

NSError *error = nil; 
NSArray *items = [context executeFetchRequest:fetchRequest error:&error]; 
[fetchRequest release];  

// delete roots object and let Core Data to do the rest... 
for (NSManagedObject *managedObject in items) { 
    [context deleteObject:managedObject]; 
} 

캐스케이드 그래프를 제거 규칙을 활용. 이 기능은 몇 가지 객체에서는 빠르지 만 많은 객체에서 성능이 떨어집니다. 또한이 유형의 삭제가 디스크에 많은 왕복을 수행한다고 생각합니다 (확실하지 않습니다). 제가 틀렸습니까?

그래서 내 질문은 다음과 같습니다. 계단식 규칙을 사용하지 않고 그래프를 제거하고 동시에 성능을 향상시킬 수 있지만 동시에 그래프 일관성을 유지 하시겠습니까?

미리 감사드립니다.

내 모델에서 다른 기업이 있기 때문에 내가 전체 파일을 삭제할 수 없습니다

편집 할 수 있습니다.

EDIT 2

내가 게시 된 코드는 NSOperation 서브 클래스의 main 방법에 싸여있다. 이 솔루션을 사용하면 백그라운드에서 삭제 단계를 수행 할 수 있습니다. 캐스케이드 규칙을 이용했기 때문에 삭제는 반자동 방식으로 수행됩니다. 난 오직 게시 된 코드 내에서 for 루프를 사용하여 루트 객체 인 FirstLevel 항목 만 삭제합니다. 이런 식으로 코어 데이터는 나를 위해 나머지를 할 수 있습니다. 내가 궁금해하는 것은 다음과 같다. 반자동 삭제 작업을 바이 패스하고 그래프의 일관성을 잃지 않고 수동으로 할 수 있는가?

+0

tou는 전체 그래프를 지우고 싶습니다. 즉 모든 영구 저장소를 삭제 하시겠습니까, 아니면 일부 지사를 지우시겠습니까? –

+0

전체 그래프입니다. –

+1

그러면 너에게 도움이 될거야? http : //stackoverflow.com/questions/3266084/how-to-remove-all-objects-from-core-data –

답변

5

데이터베이스에서 개체를 이동하고 제거하는 데 걸릴 시간은별로 없습니다. 그러나 UI가 차단되지 않도록 백그라운드에서 수행 할 수 있습니다. 당신이 당신의 데이터 모델에 RootLevel 개체를 추가하고, 그것을 줄 수 있다고 ...

- (void)deleteAllLevelsInMOC:(NSManagedObjectContext*)moc 
{ 
    // Create a context with a private queue, so access happens on a separate thread. 
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
    // Insert this context into the current context hierarchy 
    context.parentContext = context; 
    // Execute the block on the queue of the context 
    context.performBlock:^{ 
      NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"FirstLevel"]; 
      // This will not load any properties - just object id 
      fetchRequest.includesPropertyValues = NO; 
      // Iterate over all first-level objects, deleting each one 
      [[context executeFetchRequest:fetchRequest error:0] 
       enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
       [context deleteObject:obj]; 
      }]; 
      // Push the changes out of the context 
      [context save:0]; 
    }]; 
} 

참고 예를 들어

은 같은 (컴파일되지 코드는 ARC 가정 - - 그리고 방금 입력 한) 첫 번째 수준 개체와 일대 다 관계. 그런 다음 (하나의 루트 객체 만있는 한) 루트 객체 하나를 삭제하면 CoreData 내부의 모든 객체가 삭제됩니다. FirstLevel 객체가 많은 경우 이동 방법입니다.

또는 "새"컨텍스트를 영구 저장소에 직접 연결하고 변경 한 다음 다른 컨텍스트에서 변경 알림을 볼 수 있습니다.

현재 UIManagedDocument를 사용하는 경우 이미 자체 대기열에서 상위 컨텍스트가 실행 중이므로 주체 컨텍스트에 대한 모든 변경 사항이 실제로 수행되도록 부모에게 전달되므로 무료로이 유형의 배경을 얻습니다. 데이터베이스 작업.

편집

당신은 수동으로 할 수 있지만 캐스케이드 규칙을 해제해야합니다. 나는 CoreData가 가능한 한 많이 나를 원한다는 것을 발견했다. 오류에 대한 나의 마진을 줄입니다.

이미 백그라운드 스레드에서 삭제하는 경우 성능 문제는 어떻게 확인합니까? 삭제 중에 쿼리를해야합니다 ... 즉 모든 작업을 수행하는 MOC를 사용하고 있음을 의미합니다.

UIManagedDocument에서 강의를 가져와야합니다. 개인 대기열에서 실행되는 MOC가 있어야합니다. 모든 실제 작업을 수행합니다. 작업자 큐로 작업을 전달하는 하위 MOC가 있습니다.

삭제하려는 그래프에없는 개체를 실제로 쿼리하는 경우 영구 저장소 코디네이터의 serializing 속성에 의해 중단 될 수 있습니다. 이 경우 별도의 조정자를 고려하거나 두 개의 점포 만 보유해야합니다.

그런 식으로 다른 개체에 대한 요청에 응답하면서 원하는만큼 그래프의 개체를 삭제할 수 있습니다.

+0

+1. 이미 백 스레드에서 삭제하고 있습니다. "새"컨텍스트를 영구 저장소에 직접 연결하고 변경 한 다음 다른 컨텍스트에서 변경 알림 *을 볼 수있는 것이 무엇인지 더 잘 설명해 주실 수 있습니까? 고맙습니다. –

+0

어쩌면 전체 삭제 코드를 게시 할 수 있습니다 ... 두 번째 부분에서는 동일한 NSPersistentStoreCoordinator를 사용하는 여러 MOC를 만들 수 있습니다. 그러나 이것은 상점에 대한 액세스를 직렬화합니다 ... 또한 별도의 NSPersistentStoreCoordinator를 작성할 수 있으며 상점에 병렬 액세스 할 수 있지만 처리 할 다른 문제점이 있습니다. 일반적으로 가장 간단한 솔루션이 항상 최상입니다. –

+0

답장을 보내 주셔서 감사합니다. 여러 MOC를 만드는 것이 유효한 해결책이 될 수 있지만 한 번의 통과로 삭제 작업을 완료해야합니다. 내 두 번째 편집을 참조하십시오. 다시 감사합니다. –

1

일반적으로 여기에 설명 된대로 -com.apple.CoreData.SQLDebug 1으로 코어 데이터 SQL 추적을 설정합니다. http://useyourloaf.com/blog/2010/3/11/debugging-core-data-on-the-iphone.html 이렇게하면 코어 데이터가 내에서 수행 할 것으로 예상되는 동작을 확인하는 데 도움이됩니다.

[moc save : ...]는 삭제 될 객체를 가져 오기 위해 실제 fetchrequest가 아니라 오래 걸리는지 확인 했습니까? 이 경우 배치에서 첫 번째 수준의 객체를 가져 와서 삭제할 수 있습니다.