对数据库执行大量读/写操作的方法
Posted
技术标签:
【中文标题】对数据库执行大量读/写操作的方法【英文标题】:method for performing lot of read/write operations on a database 【发布时间】:2012-04-16 15:55:02 【问题描述】:我正在开发一个 iPad 应用程序,我必须在其中对数据库执行大量读/写操作(我必须根据点击将视图上的点击存储在数据库中,然后执行一些操作)。我对在这种情况下如何进行感到困惑。我应该只创建一个 SQLite 数据库并执行读/写(这会减慢应用程序的响应时间吗??)还是有其他一些技术(我听说过核心数据,但不确定这是否适用于我的情况) . 请帮帮我
谢谢
阿吉特
【问题讨论】:
【参考方案1】:如果您只是按顺序保存它们,然后以相同的顺序读回它们,那么常规文件可能是最好的。但是,如果您要执行其他任何操作,请使用 CoreData。它不仅仅是一个关系数据库。它允许持久对象图。此外,如果您使用 UIManagedDocument 或您自己的父/子 NSManagedObjectContext 安排,您甚至不会看到数据库命中,因为这一切都发生在后台线程中。
继续,测试一下。覆盖开始/移动/结束触摸,并在每次触摸时将对象放入数据库。如果您按照我的描述进行操作,您甚至不会注意到数据库命中。
假设模型中有两个实体,MyTouchEvent 和 MyTouch,其中 MyTouchEvent 与 MyTouch 是一对多的关系。
// Call this from touchesBegan, touchesMoved, and touchesEnded...
- (void) saveTouches:(NSSet*)touches kind:(NSString*)kind
NSManagedObjectContext *moc = self.document.managedObjectContext;
MyTouchEvent *myTouchEvent = [NSEntityDescription insertNewObjectForEntityForName:@"MyTouchEvent" inManagedObjectContext:moc];
myTouchEvent.kind = kind;
for (UITouch *touch in touches)
CGPoint touchPoint = [touch locationInView:self];
MyTouch *myTouch = [NSEntityDescription insertNewObjectForEntityForName:@"MyTouch" inManagedObjectContext:moc];
myTouch.x = [NSNumber numberWithFloat:touchPoint.x];
myTouch.y = [NSNumber numberWithFloat:touchPoint.y];
[myTouchEvent addTouchesObject:myTouch];
[self.document updateChangeCount:UIDocumentChangeDone];
如果您的对象创建成本很高,您可以添加一个方法来创建私有上下文,并在其中完成所有工作,有两种选择。您可以将其作为文档的主上下文的父级,在这种情况下,您所要做的就是将代码嵌入到一个块中,然后在 MOC 上调用 save...
- (NSManagedObjectContext*)moc
if (!_moc)
_moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
_moc.parentContext = self.document.managedObjectContext;
return _moc;
- (void) saveTouches:(NSSet*)touches kind:(NSString*)kind
NSManagedObjectContext *moc = self.moc;
[self.moc preformBlock:^
MyTouchEvent *myTouchEvent = [NSEntityDescription insertNewObjectForEntityForName:@"MyTouchEvent" inManagedObjectContext:moc];
myTouchEvent.kind = kind;
for (UITouch *touch in touches)
CGPoint touchPoint = [touch locationInView:self];
MyTouch *myTouch = [NSEntityDescription insertNewObjectForEntityForName:@"MyTouch" inManagedObjectContext:moc];
myTouch.x = [NSNumber numberWithFloat:touchPoint.x];
myTouch.y = [NSNumber numberWithFloat:touchPoint.y];
[myTouchEvent addTouchesObject:myTouch];
NSError *error = nil;
[moc save:&error];
];
或者,您可以将其设为兄弟,在这种情况下,所有数据库都不会在主线程上运行(UIManagedDocument 的主上下文在主线程上运行,因此在上述情况下,主线程将将对象传递给执行保存的上下文)。但是,在这种情况下,您的 document.managedObjectContext 必须执行 FETCH 才能获取放入数据库的任何内容。但是,它在存储过程中不会导致主线程的性能。
- (NSManagedObjectContext*)moc
if (!_moc)
_moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
_moc.parentContext = self.document.parentContext;
return _moc;
现在,这些将进入数据库,但如果您的文档想要查看它们,则必须执行提取。根据您的用例选择最好的。不过,我想你会很好地处理第一个例子。
【讨论】:
【参考方案2】:如果有很多点击,你肯定不希望将它们中的每一个单独写入数据库。或许,累积鼠标操作并将其保存在-mouseUp:
事件中会是一个不错的折衷方案。
Core Data 可以通过简化程序来提供一些帮助。它使您可以非常快速地创建对象并推迟将它们保存到持久存储中。但是如果你安装一个CFRunLoopObserver
,你可以用SQLite达到同样的效果,等到没有事件,然后将一批数据写入数据库。
无论你选择什么,策略都是累积点击并分批保存。
【讨论】:
【参考方案3】:您最好的选择是将您的操作流式传输到文件系统上的文件中。然后你可以把它留在那里,或者如果你真的需要,通过 Core Data 将它上传到 SQLite。这样做的原因是,如果你为每个偶数提交 ManagedObjectContext
,事情会运行得非常慢。
使用:backingFile = [NSFileHandle fileHandleForUpdatingAtPath:eventsFilePath];
将您的事件附加到使用 [backingFile writeData:...];
请记住,关系数据库的主要目的是“搜索”数据。如果您不打算搜索 UI 点击事件(我怀疑您会这样做),那么流式传输到文件是您的最佳选择。
【讨论】:
以上是关于对数据库执行大量读/写操作的方法的主要内容,如果未能解决你的问题,请参考以下文章