2012-05-04 3 views
6

결론
문제가 해결 된 것 같습니다.
문제는이 방법론과는 아무런 관련이없는 것처럼 보이지만 XCode는 빌드간에 올바르게 프로젝트를 정리하지 못했습니다.
모든 테스트가 끝난 후에 사용 된 sqlite 파일은 아직 색인이 생성되지 않은 첫 번째 파일이었습니다 ......
Xcode 4.3.2에주의하십시오. Clean 청소, 또는 ... 자동으로 번들 리소스에 추가되지 않는 다른 답변을
감사합니다 ..대용량 CSV 파일을 코어 데이터에로드하는 가장 빠른 방법은 무엇입니까

업데이트를 프로젝트에 파일을 추가하지 않는 3
난 그냥 확인하기 위해 동일한 단계를 시도하는 사람을 초대하기 때문에 그들이 동일한 결과를 얻는다면, 내가 한 일을 상세히 설명해 드리겠습니다.
빈 프로젝트로 시작합니다
populateDb에 대한

[self performSelectorInBackground:@selector(populateDB) withObject:nil]; 

코드 :나는 첫 번째 문자열은 enter image description here

에서, 나는 finishLaunchingWithOptions 호출 오전 않았다
를 인덱싱 한 법인, 3 개 특성 (2 문자열, 1 플로트)
와 데이터 모델을 정의

-(void)populateDB{ 
NSLog(@"start"); 
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 
NSManagedObjectContext *context; 
if (coordinator != nil) { 
    context = [[NSManagedObjectContext alloc] init]; 
    [context setPersistentStoreCoordinator:coordinator]; 
} 

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"input" ofType:@"txt"]; 
if (filePath) { 
    NSString * myText = [[NSString alloc] 
           initWithContentsOfFile:filePath 
           encoding:NSUTF8StringEncoding 
           error:nil]; 
    if (myText) { 
     __block int count = 0; 


     [myText enumerateLinesUsingBlock:^(NSString * line, BOOL * stop) { 
      line=[line stringByReplacingOccurrencesOfString:@"\t" withString:@" "]; 
      NSArray *lineComponents=[line componentsSeparatedByString:@" "]; 
      if(lineComponents){ 
       if([lineComponents count]==3){ 
        float f=[[lineComponents objectAtIndex:0] floatValue]; 
        NSNumber *number=[NSNumber numberWithFloat:f]; 
        NSString *string1=[lineComponents objectAtIndex:1]; 
        NSString *string2=[lineComponents objectAtIndex:2]; 
        NSManagedObject *object=[NSEntityDescription insertNewObjectForEntityForName:@"Bigram" inManagedObjectContext:context]; 
        [object setValue:number forKey:@"number"]; 
        [object setValue:string1 forKey:@"string1"]; 
        [object setValue:string2 forKey:@"string2"]; 
        NSError *error; 
        count++; 
        if(count>=1000){ 
         if (![context save:&error]) { 
          NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]); 
         } 
         count=0; 

        } 
       } 
      } 



     }]; 
     NSLog(@"done importing"); 
     NSError *error; 
     if (![context save:&error]) { 
      NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]); 
     } 

    } 
} 
NSLog(@"end"); 
} 

그 밖의 모든 것은 기본 코어 데이터 코드이며 아무 것도 추가되지 않습니다.
시뮬레이터에서 실행했습니다.
내가 갈 ~/라이브러리/응용 프로그램 생성 된 SQLite는 파일이
지원/아이폰 시뮬레이터/5.1/응용 프로그램 // 문서

나는 그것을 받아 내 번들

I 코멘트에 복사 전화에서 처음 실행

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator 
{ 
@synchronized (self) 
{ 
    if (__persistentStoreCoordinator != nil) 
     return __persistentStoreCoordinator; 

    NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"myProject" ofType:@"sqlite"]; 
    NSString *storePath = [[[self applicationDocumentsDirectory] path] stringByAppendingPathComponent: @"myProject.sqlite"]; 

    NSError *error; 
    if (![[NSFileManager defaultManager] fileExistsAtPath:storePath]) 
    { 
     if ([[NSFileManager defaultManager] copyItemAtPath:defaultStorePath toPath:storePath error:&error]) 
      NSLog(@"Copied starting data to %@", storePath); 
     else 
      NSLog(@"Error copying default DB to %@ (%@)", storePath, error); 
    } 

    NSURL *storeURL = [NSURL fileURLWithPath:storePath]; 

    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
          [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil]; 

    if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) 
    { 

     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     abort(); 
    }  

    return __persistentStoreCoordinator; 
}  
} 


012에서 문서에 번들에서 sqlite가 파일을 복사 persistentStoreCoordinator을 편집

을 populateDb하기시뮬레이터에서 앱을 제거하고 ~/Library/Application Support/iPhone Simulator/5.1/Applications /가 이제 제거되었음을 확인하십시오.
다시 빌드하고 다시 실행하십시오.
예상대로 sqlite 파일이 ~/Library에 복사됩니다./Application Support/iPhone Simulator/5.1/Applications // Documents

그러나 파일의 크기가 번들보다 작습니다. 또한 다음과 같은 조건자를 사용하여 간단한 쿼리를 수행합니다. [NSPredicate predicateWithFormat : @ "string1 == % @", string1]; 분명히 문자열 1이, 난 그냥
시뮬레이터에서 실행하는 경우 경량 마이그레이션을 강제로, 의미없는 업데이트는 데이터 모델의 새 버전을 만들 더 이상


색인 그 다음되지 않는다는 것을 보여주고, 마이그레이션은 몇 소요 초 만에 데이터베이스의 크기가 두 배로 늘어 났으며 동일한 쿼리가 이제는 분이 아닌 일 초 만에 반환됩니다.
이것은 내 문제를 해결하고 강제로 마이그레이션을 수행 할 수 있지만 동일한 마이그레이션은 iPad에서 3 분이 걸리고 포 그라운드에서 발생합니다.
모자를 쓰고있는 바로 지금, 나에게 가장 좋은 해결책은 여전히 ​​색인을 제거하지 못하게하는 것입니다. 실행시 다른 가져 오기 솔루션은 너무 많은 시간이 걸립니다.
더 해명이 필요하면 알려주세요 ...

업데이트 2
그래서 내가 지금까지 가지고있는 최고의 결과가 유사과 빠른 도구에서 생성 된 SQLite는 파일로 핵심 데이터베이스를 시드하는 것입니다 데이터 모델이지만 sqlite 파일을 생성 할 때 인덱스가 설정되지 않습니다. 그런 다음 인덱스가 설정된 핵심 데이터 응용 프로그램에서이 sqlite 파일을 가져 와서 간단한 마이그레이션을 허용합니다. 새로운 iPad에 200 만 건의 기록을 남기려면이 마이그레이션 스틸은 3 분이 걸립니다. 최종 앱의 레코드 수는이 5 배가되어야하므로 처리 시간이 오래 걸립니다. 그 경로를 선택하면 새로운 질문이 생깁니다 : 백그라운드에서 간단한 마이그레이션을 수행 할 수 있습니까?

업데이트
내 질문은 코어 데이터의 데이터베이스를 채우는 한 다음 내 응용 프로그램에 sqlite가 파일을 가져올 수있는 도구를 만드는 방법이 아닙니다.
나는 이것을 어떻게하는지 안다. 나는 그것을 무수히했다.
하지만 지금까지는 그런 방법이 약간의 부작용을 일으킬 수 있다는 것을 깨닫지 못했습니다. 제 경우에는 결과 데이터베이스의 색인 된 속성이 sqlite 파일을 가져올 때 명확하게 '색인 해제'되어 나타납니다.
그러한 전송 후에도 색인 된 데이터가 여전히 색인화되어 있는지 확인할 수 있다면 진행 방법을 알고 싶거나 그러한 데이터베이스를 효율적으로 시드하는 최상의 전략이 무엇인지 알고 싶습니다.

원래

나는 4 열, 문자열과 수레와 큰 CSV 파일 (라인의 수백만)이있다. iOS 앱용입니다.

앱을 처음로드 할 때 핵심 데이터에로드해야합니다.

데이터가 사용 가능할 때까지는 앱이 거의 작동하지 않으므로 처음로 사용자가 앱을 실행하기 전에로드하는 데 20 분이 걸리지 않으므로 로딩 시간이 중요합니다.

지금 현재 코드는 2 백만 줄의 CSV 파일을 처리하기 위해 새 iPad에서 20 분이 걸립니다.

배경 컨텍스트를 사용하여 UI를 잠그지 않고 1,000 레코드마다 컨텍스트를 저장합니다.

시뮬레이터에서 데이터베이스를 생성 한 다음 문서 폴더에 복사/붙여 넣기했습니다. 첫 번째 출시는 대용량 데이터베이스 구축을위한 공식적인 방식이 아니기 때문에 가능합니다. 유감스럽게도, 인덱스는 그러한 전송에서 살아남지 못하는 것 같습니다. 데이터베이스가 단 몇 초 만에 사용 가능했지만 인덱스가 손실 되었기 때문에 성능이 심각합니다. 이미 인덱스에 관한 질문을 게시했지만 좋은 대답은 아닌 것 같습니다.

  • 데이터베이스가 미리로드하고 처음 시작할 때 이동 한 경우 핵심 데이터에
  • 을 기록 수백만로드에 대한 성능을 개선 할 수있는 방법, 방법 : 나는 대한 하나를 찾고 있어요 그래서

    내 인덱스를 유지하려면
  • 이러한 종류의 시나리오를 처리하는 모범 사례.처음 사용하기 전에 x 분 동안 기다려야하는 앱을 사용하는 것을 기억하지 않습니다 (그러나 Daily, 아마도 끔찍한 경험이었습니다).
  • 튜토리얼 등을 진행하면서 배경 가져 오기 ...
  • 핵심 데이터를 사용하고 있지 않습니까?
  • ...
+0

그럼 제대로 작동하도록 프로젝트를 "정리"하는 방법은 무엇입니까? – lnafziger

+0

클린이 작동하지 않았지만 랩탑을 재부팅하고 파일에 대한 모든 참조를 수동으로 청소하는 등의 작업은 문제를 '해결 한'것으로 보입니다. 이상한 ... 비록 내가 마이그레이션하지 않도록 강제로 가벼운 마이그레이션 라인을 제거해야했지만 (이것은 많은 시간이 걸릴 것입니다). 전반적으로, 이것은 내가 바라는 깨끗한 구현이 아니지만,이 작업은 ... 버전 2에서 데이터 모델 업그레이드가 필요할 때까지는 문제가 있습니다. –

답변

6

사전 생성 OS X에서 실행, 동일한 코어 데이터 프레임 워크를 사용 코코아로 작성된 오프라인 응용 프로그램 (예를 들어, 명령 줄 유틸리티)를 사용하여 데이터베이스를, 그 아이폰 OS 사용 . "인덱스 생존"또는 그 밖의 모든 것에 대해 걱정할 필요가 없습니다. 출력물은 Core Data에서 생성 된 .sqlite 데이터베이스 파일이며 iOS 앱에서 직접 사용할 수 있습니다.

DB 생성을 오프라인으로 수행 할 수있는 한 가장 좋은 해결책입니다. 필자는이 기술을 iOS 배포 용 사전 생성 데이터베이스에 사용했습니다. 조금 더 자세하게 이전 질문/답변을 확인하십시오.

+0

색인 문제가 없는데도 동일한 작업을 수행했습니다 ... – lnafziger

+0

내 인덱스에 대해 걱정할 필요가 없다는 의미는 무엇입니까? 내 질문에 명시된 바와 같이, 나는 정확한 방법을 수행, 결과는 sqlite 데이터베이스 파일 (200Mb), 그리고 똑같은 모델로 내 응용 프로그램에서 사용하면 파일이 110Mb로 내려 갔고 명확하게 성능은 내 색인이 아니라는 것을 제안했습니다. 일. 그래서 나는 내 인덱스에 대해 걱정하고 있습니다, 이것이 전체 요점입니다! –

+0

@nafziger, 핵심 데이터 모델에 인덱스가 있다는 것을 의미합니까? 그리고 그 인덱스가 여전히 sqlite 파일을 다시 사용해야하는 것처럼 작동하는지 확인하고 있습니까? 그렇다면 인덱스가 여전히 작동하는지 확인하는 방법은 무엇입니까? –

0

저는 SQLite로 시작 했으므로 SQLite 데이터베이스에 색인 된 데이터가 많이 들어있는 내 응용 프로그램 중 하나에 DB를 통합해야합니다. 나는 내가 SQLite 파일에 내 정보를 대량으로 삽입하고 그 파일을 프로젝트에 추가 할 수있는 몇 가지 방법을 원할 수 있기를 바랬다. 질문과 제공된 답변 및 수많은 의견을 발견하고 읽은 후에 SQLite 소스를 확인하여이 문제의 머리 나 꼬리를 만들 수 있는지 확인했습니다.

처음 생각한 사실은 SQLite의 iOS 구현이 실제로 색인을 던지고 있다는 것입니다. 이유는 처음에 x86/x64 시스템에 DB 인덱스를 만들기 때문입니다. iOS는 ARM 프로세서이며 숫자는 다르게 처리됩니다. 인덱스를 빠르게하려면 인덱스가 검색 될 프로세서에 최적화 된 방식으로 인덱스를 생성해야합니다.

SQLite는 여러 플랫폼 용이므로 다른 아키텍처에서 생성 된 인덱스를 삭제하고 다시 작성하기 때문에 SQLite는 여러 플랫폼에 사용됩니다. 그러나 처음 액세스 할 때 인덱스를 다시 작성할 때까지 기다릴 사람이 없기 때문에 SQLite 개발자는 인덱스를 삭제하기로 결정했을 가능성이 큽니다.

SQLite 코드를 조사한 결과, 일 가능성이 가장 높습니다.이 발생했습니다. 프로세서 아키텍쳐 이유가 아니라면, 예기치 않은 상황에서 인덱스가 생성 된 경우 인덱스가 삭제되는 코드 (analyze.c 및 기타 메타 정보는 sqliteint.h 참조)를 찾았습니다. 이 프로세스를 주도하는 컨텍스트는 기본 키에 대해 기본 b- 트리 데이터 구조가 구성되는 방식입니다. SQLite의 현재 인스턴스가 키를 사용할 수 없으면 키를 삭제합니다.

iOS 시뮬레이터는 바로 시뮬레이터입니다. 그것은 하드웨어의 에뮬레이터가 아닙니다. 따라서 앱은 x86/x64 프로세서에서 실행되는 의사 iOS 기기에서 실행됩니다.

앱과 SQLite DB를 iOS 장치에로드하면 ARM 컴파일 변형이로드되고 iOS 내에서 ARM 컴파일 라이브러리에 링크됩니다. SQLite와 관련된 ARM 전용 코드를 찾을 수 없었기 때문에 Apple이이를 수정해야한다고 생각합니다. 또한 문제의 일부일 수 있습니다. 이것은 root-SQLite 코드에 문제가되지 않을 수도 있습니다. Apple/ARM 컴파일 된 이슈와 관련된 문제 일 수 있습니다.

내가 만날 수있는 유일한 합리적인 해결책은 iOS 컴퓨터에서 실행되는 발전기 응용 프로그램을 만들 수 있다는 것입니다. 응용 프로그램을 실행하고 키를 만든 다음 장치에서 SQLite 파일을 추출합니다. iOS에서 사용하는 모든 ARM 프로세서가 32 비트이기 때문에 이러한 파일이 모든 장치에서 작동한다고 생각합니다.

다시 말하면이 대답은 약간의 추측입니다. 질문을 SQLite로 다시 태그 지정하겠습니다. 다행히 도사가 이것을 발견하고이 문제에 무게를다는 것이 좋을 것입니다. 나는 내 자신의 이익을 위해 진실을 알고 싶다.

관련 문제