2009-07-25 7 views
2

Hey Leute, hier ist der Tiefpunkt.iPhone Sqlite Performance Problem

Ich habe eine Tabelle, bestehend aus einem Primärschlüssel (col1), Text (col2) und Text (col3). Im Grunde eine Karte. Diese Tabelle enthält ungefähr 200.000 Zeilen. Es dauert ungefähr 1.x Sekunden, um eine einzelne Zeile zu erhalten (das ist alles was ich will). Ich benutze im Grunde Select * aus der Tabelle, wo Col2 = 'ein Wert'.

Ich habe versucht, einen Index für alle drei Spalten, jede Spalte einzeln und Col2 und Col3, aber das hat wirklich nicht meine Situation überhaupt verbessert.

Ich frage mich, ist das normal? Ich habe keine Posts von Leuten gefunden, die sich über die langsame SQL-Performance für große Tische beschweren, also frage ich mich, was ich falsch mache.

Jede Hilfe würde sehr geschätzt werden.

+0

Sind Sie sicher, dass nur eine Zeile das Ergebnis ist? – Juergen

+1

Außerdem würde ich empfehlen, Instrumente oder Shark gegen Ihre Anwendung laufen zu lassen, wenn die Abfrage ausgeführt wird. Ich hatte ein ähnliches Problem und nahm an, dass es SQLite war, aber es stellte sich heraus, dass es eine suboptimale String-Parsing-Methode in meinem Code war, die die Verlangsamung verursachte. –

+0

Ja, ich bin sicher, dass nur eine Zeile zurückgegeben wird, ich werde Hai versuchen, danke für diese Idee! –

Antwort

2

Ich löste das Problem m. Als ich eine neue sqlite-Datenbankdatei erstellte und sie dem Projekt hinzufügte, wurde xcode nicht korrekt neu kompiliert, sondern es wurde immer noch die alte Datei verwendet. Ich musste die alte Datenbank aus dem Projekt entfernen, die kompilierte Version auf dem Computer entfernen, das Projekt säubern, dann kompilieren und sicherstellen, dass es abstürzte, da die Datenbank fehlte. Entfernen Sie dann erneut die kompilierten Dateien, bereinigen Sie sie und fügen Sie die neue SQLite-Datenbank erneut hinzu.

Aus diesem Grund, auch nachdem ich den Index erstellt es überhaupt keine Leistungsverbesserung ....

Seltsam, würde dies war ein Fehler mit Xcode in Betracht gezogen werden?

+0

Benutzerfehler. ;) – Sneakyness

2

Ich würde sagen, dass dies absolut nicht typisch ist.

Auch wenn Sie eine große Tabelle haben, sollte der Zugriff über einen Index ziemlich schnell sein.

Was könnten Sie tun: Erstellen Sie nur einen Index auf col2 (das ist die einzige und einzige, die Sie für diese Auswahl benötigen!).

Verwenden Sie dann "EXPLAIN SELECT ....", um die Informationen zu erhalten, was SQLite daraus macht. Das Ergebnis ist nicht einfach zu lesen, aber mit etwas Erfahrung ist es möglich zu sehen, ob der Index verwendet wird. Sie können das Ergebnis hier auch posten.

+0

Dies ist die Ausgabe von Explain select * aus der Tabelle where col1 = 'irgendwas' 0 | Gehe zu | 0 | 23 | 1 | Ganzzahl | 0 | 0 | 2 | OpenRead | 0 | 2 | 3 | SetNumColumns | 0 | 3 | 4 | Ganzzahl | 0 | 0 | 5 | OpenRead | 1 | 4 | Schlüsselinfo (1, BINARY) 6 | String8 | 0 | 0 | one 7 | IsNull | -1 | 20 | 8 | MakeRecord | 1 | 0 | a 9 | MemStore | 0 | 0 | 10 | MoveGe | 1 | 20 | 11 | MemLoad | 0 | 0 | 12 | IdxGE | 1 | 20 | + 13 | IdxRowid | 1 | 0 | 14 | MoveGe | 0 | 0 | 15 | Spalte | 0 | 0 | 16 | Spalte | 0 | 1 | 17 | Spalte | 0 | 2 | 18 | Rückruf | 3 | 0 | 19 | Weiter | 1 | 11 | 20 | Schließen | 0 | 0 | 21 | Schließen | 1 | 0 | 22 | Halt | 0 | 0 | 23 | Transaktion | 0 | 0 | 24 | VerifyCookie | 0 | 3 | 25 | Gehe zu | 0 | 1 | 26 | Noop | 0 | 0 | –

+0

argh, hier ist es schön formatiert http://dpaste.com/71454/ –

+0

Hallo Paul, wie wäre es einfügen in Ihre ursprüngliche Posting (oder eine Antwort natürlich) mit 4 Leerzeichen Leerzeichen (das ist speziell für die Codierung). Somit würde es nicht ablaufen. – Juergen

1

ich diese Klasse gemacht habe ein Singleton (genannt SQLAdapter), und diese enthält es zwei Methoden in hier, man die Datenbank, wenn es gebraucht wird zu kopieren, und das andere meine SQL-Code exec:

Hier die sQL-Code-Methode, war dies das erste Mal, dass ich in Obj-C codierte, so einfach ignoriert die String-Methoden Anfügen ich dies ändern, wie wir sprechen ...

- (NSString *)getMapping:(NSString *)test{ 
    //Our return string 
    NSString *res = test; 

    // Setup the database object 
    sqlite3 *database; 

    NSString *sqlStmnt; 
    if (direction) sqlStmnt = @"select * from table where col1 = '"; 
    else sqlStmnt = @"select * from table where col2 = '"; 

    NSString *tStmt = [sqlStmnt stringByAppendingString:test]; 
    NSString *sqlState = [tStmt stringByAppendingString:@"'"]; 
    const char * sqlStatement = [sqlState UTF8String]; 

    // Open the database from the users filessytem 
    if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) { 
     // Setup the SQL Statement and compile it for faster access 
     sqlite3_stmt *compiledStatement; 
     //execute the statement 
     if (sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) != SQLITE_OK) { 
      NSAssert1(0, @"Error: during prepare '%s'.", sqlite3_errmsg(database)); 
     } 
     //bind our translation into the sql select statment 
     sqlite3_bind_text(compiledStatement, 1 , [word UTF8String], -1, SQLITE_TRANSIENT); 
     if(sqlite3_step(compiledStatement) == SQLITE_ROW) { //if execution is successful i.e. we get a match 
      //lets return the desired language translation 
      res = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, (direction) ? 2 : 1)]; 
     } 
     sqlite3_finalize(compiledStatement); //Release the compiled statement from memory 
    } 
    sqlite3_close(database); //lets return the translation 
    return res; 
} 

so ziemlich genau die gleiche Art und Weise, Das SQLiteBooks Projekt macht es, wenn ich mich nicht irre ...

+0

Blah, das hat die Formatierung durcheinander gebracht, hier ist es schön formatiert: http://dpaste.com/71397/ –

+0

Also habe ich den Code verschoben, der die Datenbank jedes Mal öffnet, wenn ich eine Abfrage ausführen möchte, damit ich die Datenbank öffne Wenn das Programm zum ersten Mal geladen wird, führe ich nur Abfragen aus. Der Engpass scheint mit sqlte3_step (stmt) verknüpft zu sein. Das dauert definitiv am längsten. –