iOS-Objective C:如何优化sqlite查询

时间:2018-05-23 12:34:04

标签: ios objective-c performance sqlite

在我的iOS应用程序中,我添加了以下代码,用于检查数据库中是否存在数据。如果是,则更新该记录,否则插入新记录。

- (void)saveRoomsToDB:(NSArray *)room{
    NSString *dbpath = [[self documentDirectoryPath] stringByAppendingFormat:@"/"databaseName];

    database = [FMDatabase databaseWithPath:dbpath];

    if([database open]){
        [database beginTransaction];

        for (Room *roomData in room) {
            FMResultSet *result = [database executeQuery:@"SELECT RoomDesc FROM Room WHERE QMSRoomId = ?" withArgumentsInArray:@[@(roomData.RoomId)]];

            if ([result next]){
                [database executeUpdate:@"UPDATE Room SET QMSSubSectionId = ?,RoomDesc = ?,LastEditedDate = ?,RoomType = ?, isTrue = ?, CyclePerformed = ? WHERE QMSRoomId = ?" withArgumentsInArray:@[@(roomData.QMSSubSectionId), roomData.RoomDesc, roomData.LastEditDate, roomData.rt_description, @(roomData.isTrue), @(roomData.CyclePerformed), @(roomData.RoomId)]];
            } else{
                [database executeUpdate:@"INSERT INTO Room (QMSSubSectionId, QMSRoomId,RoomDesc, LastEditedDate, RoomNumber,RoomType, CyclePerformed,isTrue) VALUES (?, ?, ?, ?, ?, ?, ?, ?);" withArgumentsInArray:@[@(roomData.QMSSubSectionId), @(roomData.RoomId), roomData.RoomDesc, roomData.LastEditDate, roomData.RoomNumber, roomData.rt_description, @(roomData.CyclePerformed), @(roomData.isTrue)]];
            }
        }

        [database commit];
        [database close];
    }
}

我已将上述查询执行的日志打印为

  

2018-05-23 17:47:49.702 SterileTrakks [656:74128]没有记录的房间:7136
  2018-05-23 17:48:07.153 SterileTrakks [656:74128]插入房间完成`

我可以优化此查询插入时间吗?我考虑应用索引,但还有其他方法吗?

2 个答案:

答案 0 :(得分:0)

索引将改善SELECT时间,但会减慢插入速度。一般来说,在QMSRoomId等主键上建立索引是个好主意。

您可以通过将SELECT表达式移动到循环外部来优化SELECT部分​​,而不是执行7000 SELECT,而是预先选择一个以获得一组现有房间。您不应该在那里查询RoomDesc,而是查询SELECT QMSRoomId FROM Room,这可能会更快。然后将所有ID放入NSSet或排序的NSArray中,以便在循环中快速搜索。请注意,此类查询不需要任何索引。

要优化INSERT循环,您可以执行批量插入而不是单个记录插入(请参阅Is it possible to insert multiple rows at a time in an SQLite database?)。另一个优化是在插入大量内容时禁用索引(并在之后重新启用)。

可能有用的另一件事是分割UPDATE。如果您只有一些更新,最好分开进行更新。如果你有很多更新,实际上最好加载整个表,删除它并从头开始重新加载(没有更新)。

您应该测量算法的每个步骤,以了解哪个部分最慢。

对于您应该自问的此代码的更一般的建议是,您真的需要一次插入7000条记录吗?如果它是来自用户的动作(例如尝试在UI中导入大量数据文件)可能没问题,但是很长一段时间是预期的。如果是用于缓存目的,您可以将该缓存保留在内存中,并将其逐个异步地插入到数据库中,这样它就不会影响UX。同样对于缓存,我会考虑不完全使用SQL数据库,尤其是只读缓存。

答案 1 :(得分:0)

必须使用OOPs概念

FMResultSet *rs = [MyModel selectQuery:strquery];

            while ([rs next]) {

            }

////Store Responce DATA IN DaTABASE
 for (int i=0; i<(unsigned long)[responseObject count]; i++) {
                progVal++;
                [MyModel insertInto_papertype:[responseObject objectAtIndex:i] :tableName];
            }


///////////////INSERT DATA METHOD/////////////////////////
+(void)insertInto_papertype:(NSMutableDictionary *)mdict :(NSString *)tblnm
{
    NSLog(@"--%@",mdict);
    NSString *insertQuery=@"", *keyQuery = @"", *valueQuery=@"";
    NSString * numberReg = @"[0-9]";

    NSPredicate * numberCheck = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", numberReg];

    if([mdict count] > 0) {
        insertQuery = [NSString stringWithFormat:@"Insert into %@ (",tblnm];

        for(id key in mdict) {
            NSString *repalcedString =  [mdict valueForKey:key];

            if (![numberCheck evaluateWithObject:repalcedString]){
                @try {
                    if ([repalcedString rangeOfString:@"\'"].location != NSNotFound) {
                        repalcedString =  [repalcedString stringByReplacingOccurrencesOfString:@"\'" withString:@"\''"];
                    }
                }
                @catch (NSException *exception) {
                    NSLog(@"%@", exception.reason);
                }
                @finally {

                }
            }
            if([keyQuery isEqualToString:@""]){
                keyQuery = [NSString stringWithFormat:@"%@,",key];

                valueQuery = [NSString stringWithFormat:@" \' %@ \' ,",repalcedString];

            } else {
                keyQuery = [NSString stringWithFormat:@"%@ %@,",keyQuery,key];
                valueQuery = [NSString stringWithFormat:@"%@ \' %@ \' ,",valueQuery,repalcedString];
            }
        }


        //// removing extra , at end;
        keyQuery = [keyQuery substringToIndex:keyQuery.length-(keyQuery.length>0)];
        valueQuery = [valueQuery substringToIndex:valueQuery.length-(valueQuery.length>0)];

        //// adding remaining ) at end
        keyQuery = [NSString stringWithFormat:@"%@ )",keyQuery];
        valueQuery = [NSString stringWithFormat:@"%@ )",valueQuery];

        //// joinng the key and values for insert
        insertQuery = [NSString stringWithFormat:@"%@ %@ values (%@",insertQuery,keyQuery,valueQuery];
        NSLog(@"URL --%@",insertQuery);
        [self UpdateQuery:insertQuery];
    }


}

如果有任何查询要放在评论框中。