2

我们(工作中的 IT 部门)正在寻找构建一个 iPad 应用程序,该应用程序将采用数字 ID 并在表格中提供简单的查找。它本质上是对单个表的主键搜索,并在轻微处理后显示一个字段。

警告

该表有 450 万行,查找时间最长为 1 秒。它没有互联网连接,因此必须在设备上进行。我们有一些想法,但最有意义的是:

  1. Sqlite:它会经受住这样的滥用吗?它可以处理那么多行吗,它会做得好吗?

  2. 平面文件搜索:我们可以自己循环文件,或者将它们按前几位数字拆分,以进行一些更智能的索引。

  3. 卸载到设备上的某些 3rd 方数据库应用程序,该应用程序可以通过 API 处理它。

  4. 在我们无限的智慧中,我们完全错过了另一种东西。

我必须借此机会感谢苹果让我们自己测试变得如此容易。如果没有 Mac 或 Dev 许可证,我们不想承诺超过 2000 英镑,直到我们知道我们可以把它做好。

4

4 回答 4

3

虽然 Sqlite 应该可以正常工作,但它可能是矫枉过正。您只需要一个简单的二进制搜索即可。如果在一个大文件上速度太慢,请按前两位数将其拆分为 10 或 100 个子文件。

或者,您可以将数据加载到支持二进制搜索的CFArrayCFArrayBSearchValues中(请参阅 参考资料)。虽然这会对初始加载造成性能损失,但它在后续搜索中的性能可能比对一个或多个文件的自定义二分搜索更好。

于 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,因此即使是更大的 450 万条记录也可以轻松容纳在 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.8 ms

平均偏差:0.4 ms

最大查询时间:25.9 ms

最小查询时间:0.6 ms

于 2012-08-10T16:05:29.483 回答
0

在 iOS 上将这些数据加载到内存中是不行的。

您应该使用 SQLLite。这就是它的用途,你不会做更好的处理文件 IO 代码。

于 2012-08-10T13:23:14.330 回答