在数据库上执行大量读/写操作的方法

时间:2012-04-16 15:55:03

标签: objective-c xcode sqlite core-data

我正在开发一个iPad应用程序,我必须在数据库上执行大量的读/写操作(我必须根据点击执行某些操作将数据库中的点击存储在数据库中)。在这种情况下,我很困惑如何处理。我应该只创建一个SQLIte数据库并执行读/写(这会减慢应用程序的响应时间吗?)还是有一些其他技术(我听说过Core数据但不确定这是否适用于我的情况) 。     请帮帮我

由于

阿吉特

3 个答案:

答案 0 :(得分: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;
}

现在,这些将转到数据库,但如果您的文档想要查看它们,则必须执行提取。根据您的用例选择最佳选择。我想你会在第一个例子中做得很好。

答案 1 :(得分:0)

如果有大量点击,您绝对不希望将它们分别写入数据库。也许,积累鼠标操作并将其保存在-mouseUp:事件上是一个很好的折衷方案。

核心数据可以通过简化程序来帮助我们。它允许您非常快速地创建对象,并将它们保存到持久性存储中。但是,如果安装CFRunLoopObserver,则可以使用SQLite获得相同的效果,等待没有事件并将一批数据写入数据库。

无论您选择什么,策略都是累积点击次数并分批保存。

答案 2 :(得分:0)

最好的办法是将您的操作流式传输到文件系统上的文件中。然后您可以将其保留在那里,或者如果您确实需要,可以通过Core Data将其上传到SQLite。这样做的原因是,如果你为每一个偶数提交ManagedObjectContext,事情就会非常缓慢。

使用:backingFile = [NSFileHandle fileHandleForUpdatingAtPath:eventsFilePath];将您的活动附加到[backingFile writeData:...];

请记住,关系数据库的主要目的是“搜索”数据。如果您不打算搜索您的UI点击事件(我怀疑您会这样做),那么流式传输到文件是您最好的选择。