2012-12-04 44 views
1

在我的iPhone應用程序,我使用的SQLite數據庫,併爲我依靠fmdb。 在與iOS5的iPhone,即初始DB訪問需要,在最大,10S,但在iOS 6花費30秒和2m40s之間(這在iPhone 4和4S,iPhone上5約需15-20s)。我注意到的一件事是,時間總是一致的,如果在一部手機上花60秒,它總是會花費60秒。爲什麼在iOS6上訪問SQLite數據庫需要更長的時間?

沒有任何理由在iOS 6中使用FMDB的比對iOS 5的慢?有沒有更好的替代fmdb?

在代碼方面,這裏有一個樣品我在做什麼:

獲取數據

+ (NSMutableArray*) getLevadas 
{ 
    FMDatabase *db = [DBAdapter getDB]; 
    if([db open]) 
    { 
     FMResultSet *result = [db executeQuery:@"SELECT Levada.Levada_id, Levada.Nome, a.Nome as Inicio, b.Nome as Fim, Dificuldade.NomePT as DificuldadePT, Dificuldade.NomeES as DificuldadeES, Dificuldade.NomeEN as DificuldadeEN, Altitude, Distancia, DescricaoPT, DescricaoEN, DescricaoES, Latitude, Longitude, Autocarro, Levada.dataModificado, a.Sector, Levada.Duracao, b.Sector as SectorFim, GROUP_CONCAT(DISTINCT PalavrasChave.NomePT) as PalavrasChavePT, GROUP_CONCAT(DISTINCT PalavrasChave.NomeEN) as PalavrasChaveEN, GROUP_CONCAT(DISTINCT PalavrasChave.NomeES) as PalavrasChaveES, GROUP_CONCAT(DISTINCT Equipamento.NomeEN) as EquipamentoEN, GROUP_CONCAT(DISTINCT Equipamento.NomePT) as EquipamentoPT, GROUP_CONCAT(DISTINCT Equipamento.NomeES) as EquipamentoES, Levada.Coordenadas, Levada.LongitudeFim, Levada.LatitudeFim, Levada.PontosInteresse, GROUP_CONCAT(DISTINCT Fotos.url) as Fotos FROM Levada, Localizacoes as a, Localizacoes as b, Dificuldade, Levada_has_PalavrasChave, PalavrasChave, Levada_has_Equipamento, Equipamento, Fotos WHERE ((Inicio_id = a.Localizacoes_id) AND (Fim_id = b.Localizacoes_id) AND (Levada.Dificuldade_id = Dificuldade.Dificuldade_id) AND (Levada.Levada_id = Levada_has_PalavrasChave.Levada_id) AND (PalavrasChave.PalavrasChave_id = Levada_has_PalavrasChave.PalavrasChave_id) AND (Levada.Levada_id = Levada_has_Equipamento.Levada_id) AND (Levada_has_Equipamento.Equipamento_id = Equipamento.Equipamento_id) AND Levada.Levada_id = Fotos.idLevada) GROUP BY Levada.Levada_id ORDER BY Levada.Nome;"]; 

     NSMutableArray *levadas = [[NSMutableArray alloc] init]; 

     while ([result next]) 
     { 
      Levada *l = [[Levada alloc] init]; 
      [l ID:[NSNumber numberWithInt: [result intForColumn:@"Levada_id"]]]; 
      [l Nome:[result stringForColumn:@"Nome"]]; 
      [l Dificuldade:[result stringForColumn:[NSString stringWithFormat:@"Dificuldade%@", NSLocalizedString(@"lingua", NULL)]]]; 
      [l Distancia:[result objectForColumnName:@"Distancia"]]; 
      [l Duracao:[result stringForColumn:@"Duracao"]]; 
      [l Inicio:[result stringForColumn:@"Inicio"]]; 
      [l Fim:[result stringForColumn:@"Fim"]]; 
      [l Altitude:[result stringForColumn:@"Altitude"]]; 
      [l PalavrasChave:[[result stringForColumn:[NSString stringWithFormat:@"PalavrasChave%@", NSLocalizedString(@"lingua", NULL)]] stringByReplacingOccurrencesOfString:@"," withString:@", "]]; 
      [l Descricao:[result stringForColumn:[NSString stringWithFormat:@"Descricao%@", NSLocalizedString(@"lingua", NULL)]]]; 
      [l Fotos: [[result stringForColumn:@"Fotos"] componentsSeparatedByString:@","]]; 
      [l Latitude:[NSNumber numberWithDouble:[[result stringForColumn:@"Latitude"] doubleValue]]]; 
      [l LatitudeFim:[NSNumber numberWithDouble:[[result stringForColumn:@"LatitudeFim"] doubleValue]]]; 
      [l Longitude:[NSNumber numberWithDouble:[[result stringForColumn:@"Longitude"] doubleValue]]]; 
      [l LongitudeFim:[NSNumber numberWithDouble:[[result stringForColumn:@"LongitudeFim"] doubleValue]]]; 
      [l Coordenadas:[result stringForColumn:@"Coordenadas"]]; 
      [l Equipamento: [[result stringForColumn:[NSString stringWithFormat:@"Equipamento%@", NSLocalizedString(@"lingua", NULL)]] componentsSeparatedByString:@","]]; 
      [l DataModificado:[result stringForColumn:@"dataModificado"]]; 
      [l Sector: [result stringForColumn:@"Sector"]]; 
      [l SectorFim: [result stringForColumn:@"SectorFim"]]; 
      [l Autocarro: [result stringForColumn:@"Autocarro"]]; 
      [levadas addObject:l]; 
     } 
     [result close]; 
     [db close]; 
     return levadas; 
    } 
    return nil; 
} 

打開DB

+ (FMDatabase*) getDB 
{ 
    [DBAdapter copyDatabaseIfNeeded]; 
    FMDatabase *db = [FMDatabase databaseWithPath:[DBAdapter getDBPath]]; 
    [db setLogsErrors:YES]; 
    return db; 
} 
+ (void) copyDatabaseIfNeeded 
{ 
    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    NSError *error; 
    NSString *dbPath = [DBAdapter getDBPath]; 
    BOOL success = [fileManager fileExistsAtPath:dbPath]; 

    if(!success) 
    { 
     NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"WalkMe.sqlite"]; 
     success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error]; 
    } 
} 
+ (NSString *) getDBPath 
{ 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDir = [paths objectAtIndex:0]; 
    return [documentsDir stringByAppendingPathComponent:@"WalkMe.sqlite"]; 
} 

更新:

這裏的時間分析的截圖:

time profiling

從我可以收集最耗時的是[FMResultSet明]指令,更具體的rc = sqlite3_step([_statement statement]);的FMDB下一個代碼內。所以我猜猜這個問題真的是SELECT語句。

更新2:

我試過SQL語句簡化爲SELECT Levada_id FROM Levada,它仍然需要太多的時間在[FMResultSet明]務必清理項目

+1

你試過[分析](https://developer.apple.com/library/ios/#documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/AnalysingCPUUsageinYourOSXApp/AnalysingCPUUsageinYourOSXApp.html#//apple_ref/doc/uid/TP40004652-CH16-SW1)您的應用程序查看在此過程中大部分CPU時間花費在哪裏?它可以幫助您在代碼,FMDB或Apple中追蹤問題並報告。 – Joe

+0

我還沒有,但只要我能夠做到這一點,謝謝你提到它 –

+0

這不太可能,但你是從多個隊列/線程訪問數據庫嗎? – Rob

回答

2

已經花了一些時間,通過FMDB碼詳細去,那裏什麼也沒有這將佔到那些五花八門的延遲。 FMDB是一個非常薄的包裝,幾乎可以肯定不會對行爲負責。還有足夠的SQLite/FMDB用戶,如果在iOS 6中實際存在SQLite/FMDB相關問題,我會非常驚訝。如果有的話,我會認爲我們現在會聽到很多關於它的信息。

但是,在你的SELECT語句,這似乎是一個非常複雜的看了一眼,如果我是打賭錢,如果這個問題實際上是相關的數據庫,我敢打賭,這就是延遲的來源。如果您單步執行代碼,這將很容易驗證。或者在之前和之後放置NSLog語句,您將得到時間戳日誌語句,這說明了問題。

底線,假設這個問題實際上是與數據庫相關,它幾乎肯定一個SQLite問題。如果您重寫此函數以使用sqlite3_xxx()調用完成所有操作,則可能會看到相同的性能問題。話雖如此,我還沒有看到FMDB/SQLite在轉移到iOS6時的任何性能問題。如果iOS 6上的SQLite/FMDB存在一些廣泛的性能問題,我也會認爲我們會聽到血液凝結的嚎叫。

我將重點放在通過SQLite的EXPLAIN SQL語句,然後優化表,確保您有適當的索引或重建SQL。只需在計算機上的SQLite中打開數據庫,然後嘗試分析那裏的查詢。

在什麼可能會導致這種性能問題的在iOS 6 VS iOS 5的方面,我不熟悉它是如何打開數據庫的任何變化。

這將是非常有趣的,聽到的,如果你的分析證實了問題的SQLite,或者更確切地說,如果它的東西完全無關的SQLite/FMDB。


更新:

我決定去檢查,看看是否有在的iOS 5.1.1和6.0.1 SQLite的配置之間的任何有趣的配置更改,但沒有跳出我。 (不同的線程模型肯定會影響性能,但它們看起來是一樣的)。iOS 6肯定會使用稍微更新版本的SQLite,但我懷疑這會對其產生負面影響。

 

Device: iPhone OS 
iOS: 5.1.1 
SQLite Configuration: 
    Version: 3.7.7 
    Threadsafe: Yes 
    Options: 
    ENABLE_FTS3: Yes 
    ENABLE_FTS3_PARENTHESIS: Yes 
    ENABLE_LOCKING_STYLE=1: Yes 
    ENABLE_RTREE: Yes 
    OMIT_AUTORESET: Yes 
    OMIT_BUILTIN_TEST: Yes 
    OMIT_LOAD_EXTENSION: Yes 
    TEMP_STORE=1: Yes 
    THREADSAFE=2: Yes 
 
Device: iPhone OS 
iOS: 6.0.1 
SQLite Configuration: 
    Version: 3.7.13 
    Threadsafe: Yes 
    Options: 
    CURDIR: Yes 
    ENABLE_FTS3: Yes 
    ENABLE_FTS3_PARENTHESIS: Yes 
    ENABLE_LOCKING_STYLE=1: Yes 
    ENABLE_RTREE: Yes 
    OMIT_AUTORESET: Yes 
    OMIT_BUILTIN_TEST: Yes 
    OMIT_LOAD_EXTENSION: Yes 
    TEMP_STORE=1: Yes 
    THREADSAFE=2: Yes 
+0

在iOS5中,甚至在Android這個查詢需要,normaly,〜5秒來執行,我有唯一麻煩的是要了解爲什麼要花那麼多時間.. 但是明天早上我會盡力來測量時間和簡化SQL語句並查看是否有任何性能增益。 謝謝:) –

+0

對不起,我忍不住了。僅供參考,我用5.1.1 v 6.0中的SQLite配置設置更新了我的答案,並且在那裏我沒有看到任何重要的東西。嘆。 (順便說一句,我沒有注意到6.0中基於FMDB的應用程序的任何性能下降,我急切地期待着您的分析練習,看看您是否確認了任何與SQLite相關的問題,或者它是否完全是某種東西無關) – Rob

+0

你可能幫助更多比你知道的:P。 我更新我的問題與圖像的時間分析,我會盡量簡化SELECT語句,並看看是否有幫助。 –

相關問題