2011-07-30 40 views
0

對於我的iPhone應用程序,我爲Core Data設置了一個數據模型。它包含一個實體Words,其屬性爲language : String,length : Integer16word : String核心數據:獲取項目的速度很慢

我預填充我的模型的SQLite數據庫使用相同的數據模型和應對填充數據庫應用程序的主寫一個單獨的iPhone應用程序單詞列表(200K項目)。

現在使用NSFetchedRequest,我可以按照我喜歡的方式查詢託管對象,但結果很慢。我用下面的方法:

- (NSString *)getRandomWordLengthMin:(int)minLength max:(int)maxLength 
{ 
    NSString *word = @""; 

    MyAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]; 
    NSManagedObjectContext *context = [appDelegate managedObjectContext];  
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Words" 
               inManagedObjectContext:context]; 
    [fetchRequest setEntity:entity]; 

    NSString *predicateString = @"length >= %d AND length <= %d"; 
    NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString, 
           minLength, maxLength]; 
    [fetchRequest setPredicate:predicate]; 

    NSError *error = nil; 
    int entityCount = [context countForFetchRequest:fetchRequest error:&error]; 
    [fetchRequest setFetchLimit:1]; 
    if(entityCount != 0) 
    { 
     [fetchRequest setFetchOffset:arc4random()%entityCount]; 
    } 

    NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error]; 
    if([fetchedObjects count] != 0) 
    { 
     Words * test = [fetchedObjects objectAtIndex:0]; 
     word = [NSString stringWithFormat:@"%@", [test word]]; 
    } 

    return word; 
} 

使用我已經在列zLength手動設置相關的指數的SQLite的編輯,但這並沒有帶來任何的加速。瓶頸在哪裏?

編輯:

我想通了,讓int entityCount = ...是緩慢的。但是,即使讓所有的對象,然後選擇一個隨機字很慢:

Words * test = [fetchedObjects objectAtIndex:arc4random()%[fetchedObjects count]]; 

回答

3

您有效跑這裏兩次存取,一個得到讀取計數,然後一個獲取實際的對象。這會減慢速度。

你的謂語是 「倒退」。複合謂詞評估第一個表達式,例如length >= %d,然後評估第二個例如length <= %d只針對第一個結果。因此,您應該先進行消除大多數對象的測試。在這種情況下,可能length <= %d消除更多的對象,所以它應該是第一位的謂語。

既然你實際上並不需要整個Words管理對象,但只是word字符串,可以抓取返回類型設置爲NSDictionaryResultType,然後設置屬性讀取到剛剛word屬性。這會大大加快速度。

您的問題的一部分在於Core Data設計用於管理結構化對象圖,並且您正在使用隨機/非結構化圖形,因此您正在削減Core Data的優化效果。

+0

謝謝,現在我只提取一個具有固定長度的屬性(最小/最大值顯着減慢)。 – Norbert

1

不要使用SQLite編輯器編輯SQLite的後備存儲的核心數據存儲。數據庫的內部部分是私人的,可能會發生變化。

取而代之,轉到Xcode中的模型編輯器,並簡單地勾選要索引的實體屬性的「索引」選項。

不知道,但也許這謂詞是比較容易優化:

NSString *predicateString = @"length BETWEEN (%d, %d)"; 
+0

似乎'BETWEEN'是不可能的。另見[這篇文章](http://stackoverflow.com/questions/5758730/predicate-search-in-core-data-causes-sigabrt-on-second-time-through-nsbetweenpre/5759570#5759570)。 – Norbert

相關問題