7

iOS 5 で sqlite を使用しているときに 1 つの問題に直面しています。2 つのテーブルからレコードをフェッチしています。

Recipe テーブルからすべてのレコードをrecipeid取得し、それに基づいて食材テーブルからレコードを取得します。iOS 4.2 で実行するとレコードのフェッチに時間がかかりませんが、iOS 5 で実行するとレコードのフェッチに時間がかかります。次のコードを参照してください。

NSString *query = [NSString stringWithFormat:@"select id from Recipes"];
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, [query UTF8String], -1, &selectstmt, NULL) == SQLITE_OK) {
    while(sqlite3_step(selectstmt) == SQLITE_ROW) {
        rcp.recipeID = sqlite3_column_int(selectstmt, 0);
        NSString *sql = [NSString stringWithFormat:@"select Name from Ingredients where recipeId = %d",rcp.recipeID];
        sqlite3_stmt *stmt2;
        if(sqlite3_prepare_v2(database, [sql UTF8String], -1, &stmt2, NULL) == SQLITE_OK) {
            while(sqlite3_step(stmt2) == SQLITE_ROW) {}
        }
    }
}

この問題が iOS 5.0 で発生するのはなぜですか? 同じコードが iOS 4.0、4.2 でも問題なく動作します。

私が書いたコードが正しいことはわかっています。Sqlite bcoz の iOS 5.0 でのこのパフォーマンスの問題の背後にある正確な理由を知りたいのですが、私のアプリは完全にデータベースを中心に構築されています。

4

6 に答える 6

1

これはあなたが求めている答えではないかもしれませんが、パフォーマンスを改善するためのちょっとしたヒントがあります。

NSString *query = [NSString stringWithFormat:@"select id from Recipes"];
sqlite3_stmt *selectstmt;

if(sqlite3_prepare_v2(database, [query UTF8String], -1, &selectstmt, NULL) == SQLITE_OK) {
    while(sqlite3_step(selectstmt) == SQLITE_ROW) {
        rcp.recipeID = sqlite3_column_int(selectstmt, 0);

        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //NSString *sql = [NSString stringWithFormat:@"select Name from Ingredients where recipeId = %d",rcp.recipeID];//
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        sqlite3_stmt *stmt2;
        if(sqlite3_prepare_v2(database, [sql UTF8String], -1, &stmt2, NULL) == SQLITE_OK) {
            while(sqlite3_step(stmt2) == SQLITE_ROW) {}
        }
    }
}

ループを繰り返すたびにwhile、新しい NSString オブジェクト ( NSString *sql = ...) を作成するので、代わりに次のようにする必要があります。

NSString *query = [NSString stringWithFormat:@"select id from Recipes"];
NSString *sql = [NSString stringWithFormat:@"select Name from Ingredients where recipeId = %d",rcp.recipeID];
sqlite3_stmt *selectstmt;

if(sqlite3_prepare_v2(database, [query UTF8String], -1, &selectstmt, NULL) == SQLITE_OK) {
    while(sqlite3_step(selectstmt) == SQLITE_ROW) {
        rcp.recipeID = sqlite3_column_int(selectstmt, 0);
        sqlite3_stmt *stmt2;
        if(sqlite3_prepare_v2(database, [sql UTF8String], -1, &stmt2, NULL) == SQLITE_OK) {
            while(sqlite3_step(stmt2) == SQLITE_ROW) {}
        }
    }
}

これが少し役立つことを願っています!

于 2012-06-28T23:12:52.703 に答える
1

に対してリンクしたと思いますlibsqlite3.dyliblibsqlite3.0.dylib代わりにライブラリをリンクする必要があります。

于 2012-06-28T11:18:32.323 に答える
1

.db を .sqlite に変換したい場合

.db ファイルを開きます テーブルを選択します ファイル-> エクスポート--> CSV からのテーブル (.csv 形式でファイルを保存します) (このようにすべてのテーブルを選択します) 次に、.sqlite ファイルを開きます ファイル-> インポート-> テーブルから.csvファイルを選択した後のCSVは、最初の行からフィールド名を抽出する必要があるというダイアログボックスが表示され、sqliteファイルの準備ができたらチェックマークを付ける必要があります。

このファイルをプロジェクトに入れます

次に、.sqlite/.db ファイルパスを設定します

選択クエリを次のように設定します

#import <sqlite3.h>


    -(void)SelectSqlData:(NSString *)SearchString
    {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];
        NSString *path = [documentsDirectory stringByAppendingPathComponent:@"yourfileName.sqlite"];
        sqlite3_stmt *compiledStatement;
        sqlite3 *database;
        if(sqlite3_open([path UTF8String], &database) == SQLITE_OK) {

            const char *sqlStatement;

            sqlStatement = "select c.field1,c.field2,c.field3,c.field4 from YourTableName1 as c,  YourTableName2 as b  where b.Artist_Id = ?"; 

            sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL);

            //printf("\nError===%s",sqlite3_errmsg(database));


            if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {

                sqlite3_bind_text(compiledStatement,1,[SearchString UTF8String] , -1,SQLITE_STATIC);

                while(sqlite3_step(compiledStatement) == SQLITE_ROW ) 

                {

                        NSString *str_field1=[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)];

                        NSString *str_field2=[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];

                        NSString *str_field3=[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];

                        NSString *str_field4=[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)];


    // add str_field into array


            }

            }

            sqlite3_finalize(compiledStatement);


        }


        sqlite3_close(database);
    }
于 2012-06-28T12:12:06.113 に答える
1

関数 GetListBySQL は最適化されており、iOS のバージョンに依存しません。お役に立てますように。

-(NSMutableArray*)GetListBySQL:(NSString*)SQL
{
NSMutableArray* Array;

Array=[[NSMutableArray alloc]init];
NSStringEncoding enc = [NSString defaultCStringEncoding];

sqlite3_stmt *select_statement=nil;

if (sqlite3_prepare_v2(database, [SQL UTF8String], -1, &select_statement, NULL) != SQLITE_OK) {
    NSString *errString = [NSString stringWithFormat:@"%@", [@"Fail" stringByReplacingOccurrencesOfString:@"#" withString:[NSString stringWithCString:sqlite3_errmsg(database) encoding:enc] ]];
    NSAssert1(0, @"%@", errString);
}

int columncount=sqlite3_column_count(select_statement);

NSMutableDictionary* dic;

while (sqlite3_step(select_statement) == SQLITE_ROW) 
{   
    dic=[[NSMutableDictionary alloc]init];

    for(int j=0;j<columncount;j++)
    {
        if(sqlite3_column_text(select_statement, j)!=nil)
            [dic setObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(select_statement, j)] forKey:[NSString stringWithUTF8String:(char *)sqlite3_column_name(select_statement,j)]];
        else
            [dic setObject:@"" forKey:[NSString stringWithUTF8String:(char *)sqlite3_column_name(select_statement,j)]];
    }

    [Array addObject:dic];
    [dic release];      
}

sqlite3_finalize(select_statement);

NSMutableArray *arr = [[NSMutableArray alloc] initWithArray: Array];

[Array release];

return arr;
}
于 2012-06-29T13:47:56.717 に答える
0

もう 1 つの方法は、SQLite を LevelDB (google から) や TokyoCabinet などの Key/Value データベースに変更することです。私は現在2つのプロジェクトでLevelDBを使用しており、非常にうまく機能しています.TokyoCabinetも過去に使用していました.TokyoCabinetの問題はLGPLであるため、iOS環境と完全に互換性があるかどうかはわかりませんが.とにかく、東京キャビネットを使用してアプリストアにいくつかのアプリがありました(アップルには言わないでください)。

両方を使用するには、ラッパーが必要です (または、独自に開発することもできます)。これは簡単な比較と利用可能なラッパーです:

  • LevelDB : 最速の 1 つと思われます (最速ではない場合は、ベンチマークを見てください)。そして、ラッパーとして私は現在NULevelDBを使用しています。プロジェクトに追加する際に問題がある場合はお知らせください (いくつかありました)。

  • TokyoCabinet : LevelDB ほど高速ではないようですが (テストを実行していないため、ライセンスの問題で削除しました)、公式ページでは、まだテストしていないKyotoCabinetという新しいライブラリを使用することを推奨していますが、より速いはずです。私が使用したラッパーは、素晴らしいAaron Hillegass によって作成され、 BNRPersistenceと呼ばれています。

推奨事項として、LevelDB を試してみてください。背後にはより大きなコミュニティがあり、ラッパー ( NULevelDB ) はシンプルで使いやすいです。

幸運を!

于 2012-07-04T14:40:47.417 に答える