2012-08-10 46 views
2

我们(IT部门在工作)正在构建一个iPad应用程序,它将采用数字ID并在表格中提供简单的查找。它基本上是在单个表上进行主键搜索,并在进行较小处理后显示一个字段。iOS实施理论

告诫

有450万行此表中,它需要最多1秒的查找时间。它不会有互联网连接,所以它必须在设备上发生。我们有一些想法,但最有意义的:

  1. Sqlite:它会站起来如此滥用?它可以处理那么多行,它会做得好吗?

  2. 平面文件搜索:我们可以自行循环浏览文件,也可以将它们分成前几位数字,以便做出更智能的索引。

  3. 将负载卸载到可通过API处理的设备上的某些第三方数据库应用程序。

  4. 其他的东西完全是我们无法想象的。

我必须抓住机会感谢苹果让我们轻松测试自己。如果没有Mac或Dev许可证,我们不希望超过2000英镑,直到我们知道我们可以完成它。

+0

你真的试过这样做吗?花费数小时的时间将450万张记录表加载到Core Data中,然后在iPad上打开一个测试应用程序,以查看您获得结果的速度。你会得到一个关于数据大小和性能的实际概念,你不必猜测。 – Abizern 2012-08-10 13:45:24

+0

查看问题中的最后一句。我们有一个iPad,但没有开发许可证或Mac,这不是一个问题,但只是不能用于测试。我也应该说,这些都是小记录,每个小于500字节。 – Paystey 2012-08-10 13:48:50

+0

你可以请一个有开发账户和iPad的人来构建和安装它,看看结果是什么样的。或者让他们将你的设备添加到他们的开发者账户,他们可以发送给你,让你可以看到自己的样子。 – Abizern 2012-08-10 13:51:59

回答

1

SQLite速度惊人。用450万个记录A测试表具有结构:

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 

所以查询所需19ms下!虽然我没有为统计评估运行完全随机化的测试,但可以复制几个numericid值。

结论:此测试设置满足您的要求。 SQLite绝对是一种方式。

UPDATE:

100000个键值快速随机存取测试验证的第一个结果。离开SQL语句字符串创建和费时的NSLog输出了时间测量,平均数据库查询时间减少幅度为订单:

平均查询时间:1.8毫秒

平均偏差: 0.4毫秒

最大查询时间:25.9毫秒

最小查询时间:0.6毫秒

+0

太棒了,非常感谢。它比我从内存很小的sqlite中预期的要好得多。 – Paystey 2012-08-13 09:42:25

3

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

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

+0

而不是实现一个二进制搜索 - 你可以使用一个字典。 – Abizern 2012-08-10 13:01:30

+0

@Abizern是的,这也可以。 – RedFilter 2012-08-10 13:17:17

+0

我们考虑过这个问题,但是记录的数量是否会导致问题?如果我们有450万行(很小的记录,只有很多的记录),是不是很容易优化内存管理? – Paystey 2012-08-10 13:23:32

0

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

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

+0

似乎非常明确,你有数字为什么记忆是一个不行吗?或者为什么SQLite处理更好,是否不需要将它们加载到内存中以进行搜索? – Paystey 2012-08-10 13:34:00

+0

在iOS上工作了一段时间后,我会说常识意味着在移动设备上加载450万的任何东西到内存中可能是一个坏主意。你的意见可能有所不同 – 2012-08-10 13:36:38

+0

Sqlite专为具有最少资源的环境而设计。如果它将整个表加载到内存中进行查询,那么我猜我是错的。 – 2012-08-10 13:39:57

1

正如我已经评论过的那样 - 这不难测试,您可以将大型数据库加载到Core Data存储并创建一个测试应用程序,以查看结果返回的速度。

我说SQLite核心数据 - 因为它是针对平台优化的(即使它使用SQLite作为存储介质),并且编写返回值并显示它们的代码更容易。

编辑补充

我创建了一个装了11个记录和40万所记录的数据集的样本项目。此使用的核心数据在iOS 5.

然测试在我的iPad2(是2)

搜索时间3-8毫秒之间变化(0.003 - 0.008 S),较小和较大的数据集之间没有明显的差异。

这是没有优化的代码,在调试模式下运行,而不是为了任何性能增强而编写 - 搜索谓词是在每次搜索时创建的,而不是缓存的,例如没有线程。

400,000条记录的数据存储大小为17.2 MB,所以即使是较大的4.5米记录也可以轻松适用于iPad。