iOS FMDB获取大约300万个项目:由于内存问题而终止

时间:2017-02-15 03:48:22

标签: ios objective-c sqlite out-of-memory fmdb

最近我正在开发一个关于sqlite的应用程序。我使用FMDB(2.6.2),iOS使用10.2.0。数据库中有大约300万个项目。每个项目都有三个colomns:id name logo

当在UI上显示所有数据时,应用程序的要求是打击:

  • 您无法使用获取更多数据的方式(就像使用UITableViewUICollectionView滚动到底部来加载更多数据一样,但您仍然可以使用UITableView或{{1} })
  • 滚动
  • 时,用户界面必须非常流畅
  • 不要导致内存溢出

根据要求,我测试了一些条件。

我可以满足第一个和第一个要求。但是最后一个,我发现当你从db中获取所有300万个项目一次或多次时,它仍然会导致内存溢出。

以下是我在后台队列中获取数据的代码:

UICollectionView

提示:

  • dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ while (_usersArrM.count < _countNum) { NSUInteger offset = _usersArrM.count + usersFromDBOffsetCount; if (offset > _countNum) { offset = _countNum - _usersArrM.count; } else { offset = usersFromDBOffsetCount; } NSString *sql = [NSString stringWithFormat:@"select * from user limit %zd, %zd", _usersArrM.count, offset]; [_queue inDatabase:^(FMDatabase *db) { FMResultSet *userModelRS = [db executeQuery:sql]; while (userModelRS.next) { AndyUserModel *userModel = [[AndyUserModel alloc] init]; userModel.Id = [userModelRS intForColumn:@"id"]; userModel.name = [userModelRS stringForColumn:@"name"]; userModel.logo = [userModelRS stringForColumn:@"logo"]; [_usersArrM addObject:userModel]; } [userModelRS close]; }]; [_queue close]; } }); _usersArrM数据源NSMutableAarray
  • UITableView:db
  • 中项目的数量
  • _countNumusersFromDBOffsetCount
  • static NSUInteger const usersFromDBOffsetCount = 2000;_queue
  • db download:http://okufme2fh.bkt.clouddn.com/test.db.zip

我想导致内存溢出的问题是_queue = [FMDatabaseQueue databaseQueueWithPath:dbPath];,即使_queue,也不能正确释放关于db的一些内存。并且reult是循环的时候,app因内存问题而终止。

有一种方法可以在一个循环完成后完全释放db的内存。或者,满足这个应用程序的这些要求的正确方法是什么。

感谢。

1 个答案:

答案 0 :(得分:0)

在某些时候,无论您的数据框架有多好,纯粹的内存分配都会使任何功能不足的硬件崩溃。您可以尝试挖空您想要检索的数据(即

SELECT specific_col_1, specific_col_2, ... FROM table WHERE conditions

其中specific_col_i平均耗电量较低。

另一个安全措施是使用OFFSETLIMIT来限制您在任何给定时间从数据库中提取的数据量:

SELECT specific_col_1, specific_col_2, ... FROM table WHERE conditions LIMIT x OFFSET j

其中x是一次提取和处理的安全记录数,j是检索到的最后一行数的索引。您可能需要使用xj的值“播放”。

您可能必须使用智能循环算法来选择性地“引入并处理”所有这些记录。并且,如果需要,您可以将从循环中获得的批次存储到另一个表/数据库中(不确定数据处理时数据处理或数据引入后数据处理需要的确切内容)。 / p>

最后,您可能会发现LabQLite有帮助。这是我为在iOS应用程序中处理SQLite而开发的库。 LabQLite Model Generator是我创建的模型生成器,它允许您将表和视图视为Objective-C中的类(如果您使用互操作代码,则将Swift视为Swift))。 LabQLite还有大量的中低级数据库控制器方法,可能有助于改进我上面提到的循环/批处理过程。