2

私たち (職場の IT 部門) は、数値 ID を受け取り、テーブルで簡単なルックアップを提供する iPad アプリを構築しようとしています。基本的には、単一のテーブルでの主キー検索であり、マイナーな処理の後にフィールドを表示します。

警告

このテーブルには 450 万行あり、最大 1 秒のルックアップ時間が必要です。インターネット接続がないため、デバイスで実行する必要があります。いくつかのアイデアがありますが、最も理にかなっているものは次のとおりです。

  1. Sqlite: そのような悪用に耐えられるでしょうか? そんなに多くの行を処理できますか? うまく処理できますか?

  2. フラット ファイル検索: ファイルを自分でループするか、最初の数桁で分割して、もう少しインテリジェントなインデックス作成を行うことができます。

  3. API を介して処理できるデバイス上のサードパーティ データベース アプリに負荷をオフにします。

  4. 私たちの無限の叡智の中で私たちが見逃してきた、まったく別の何か。

これを自分たちで簡単にテストできるようにしてくれたアップルに感謝しなければなりません。Mac や Dev のライセンスがなければ、うまくやれることがわかるまでは 2000 ポンド以上をコミットしたくありません。

4

4 に答える 4

3

Sqlite は正常に動作するはずですが、おそらくやり過ぎです。必要なのは、単純な二分探索だけです。1 つの大きなファイルで処理が遅すぎる場合は、最初または最初の 2 桁で 10 または 100 のサブファイルに分割します。

オプションで、二分探索をサポートするCFArrayにデータをロードすることもできます(「参考文献」を参照CFArrayBSearchValues)。これにより、初期ロードのパフォーマンスが低下しますが、後続の検索では、1 つまたは複数のファイルに対するカスタム バイナリ検索よりもパフォーマンスが向上する可能性があります。

于 2012-08-10T12:52:43.013 に答える
1

コメントで既に述べたように、これをテストするのは難しくありません。大規模なデータベースを Core Data ストアにロードし、テスト アプリを作成して、結果が返される速度を確認できます。

Core Data over SQLite - プラットフォーム用に最適化されているため (ストレージ メディアとして SQLite を使用していますが)、値を返し、それらを表示するコードを簡単に記述できるためです。

編集して追加

11 レコードと 400,000 レコードのデータセットをロードするサンプル プロジェクトを作成しました。これは iOS 5 の Core Data を使用しました。

iPad2 でテストを実行しました (はい 2)

検索時間は 3 ~ 8 ミリ秒 (0.003 ~ 0.008 秒) の間で変化し、小さいデータセットと大きいデータセットの間に大きな違いはありません。

これは最適化されていないコードであり、デバッグ モードで実行され、何らかのパフォーマンス向上のために書かれたものではありません。検索述語は、キャッシュされるのではなく、検索のたびに作成されます。たとえば、スレッド化はありません。

400,000 レコードのデータストアのサイズは 17.2 MB であるため、より大きな 4.5m レコードでも iPad に簡単に収まります。

于 2012-08-10T13:50:57.050 に答える
1

SQLite は驚くほど高速です。450 万レコードのテスト テーブルには、次のような構造があります。

CREATE TABLE testtable (numericid INTEGER PRIMARY KEY, testtext TEXT);

これは、numericid (0、1、....) の増加する値と testtext の文字列で埋められます。

すべての挿入をアトミックに行うと、MacBook Pro (2009) で 1 時間 42 分かかりました。結果の SQLite ファイルのサイズは 94 MB です。

iOS アプリ内では、データベースは viewDidLoad メソッドで開かれます。次のような単純なボタン トリガー データベース クエリ:

- (void)btnPressed:(UIButton *)sender{

    NSLog(@"btn pressed, start");

    sqlite3_stmt *statement = nil;

    NSString *querystring;

    querystring= [NSString stringWithFormat:@"SELECT * FROM testtable WHERE numericid = 2571312;"];  

    const char *sql = [querystring UTF8String];

    NSLog(@"sql is: %s", sql);

    if (sqlite3_prepare_v2(dbConnection, sql, -1, &statement, NULL)!=SQLITE_OK){

        NSLog(@"sql problem occured with: %s", sql);
        NSLog(@"%s", sqlite3_errmsg(dbConnection));

    }
    else
    {

        while (sqlite3_step(statement) == SQLITE_ROW) {            

            NSString *numericid = [NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 1)];
            NSString *testtext = [NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 0)];
            NSLog(@"%@",[NSString stringWithFormat:@"%@ (%@)", numericid, testtext]);

        } // while        

    }

    sqlite3_finalize(statement);    

    NSLog(@"btn pressed, finished");    

}

次の出力が得られます。

2012-08-10 17:51:36.734 DBQueryTest[28462:707] Database Successfully Opened
2012-08-10 17:51:39.083 DBQueryTest[28462:707] btn pressed, start
2012-08-10 17:51:39.087 DBQueryTest[28462:707] sql is: SELECT * FROM testtable WHERE numericid = 2571312;
2012-08-10 17:51:39.099 DBQueryTest[28462:707] text2571312 (2571312)
2012-08-10 17:51:39.102 DBQueryTest[28462:707] btn pressed, finished

したがって、クエリは 19 ミリ秒未満で完了します。これは、numericid のいくつかの値で再現できましたが、統計的評価のために完全に無作為化されたテストは実行していません。

結論: このテスト セットアップは要件を満たしています。SQLite は間違いなく進むべき道です。

アップデート:

100000 個のキー値を使用したクイック ランダム アクセス テストにより、最初の結果が検証されます。SQL ステートメント文字列の作成と時間のかかる NSLog 出力を時間測定から除外すると、平均データベース クエリ時間は次のように 1 桁低下します。

平均クエリ時間: 1.8 ミリ秒

平均偏差: 0.4 ミリ秒

最大クエリ時間: 25.9 ミリ秒

最小クエリ時間: 0.6 ミリ秒

于 2012-08-10T16:05:29.483 に答える
0

このデータを iOS のメモリにロードすることはできません。

SQLLite を使用する必要があります。それがそのために作られたものであり、ファイル IO コードのハンドローリングを改善することはできません。

于 2012-08-10T13:23:14.330 に答える