【问题标题】:iOS-Objective C: How to optimizer sqlite queryiOS-Objective C:如何优化 sqlite 查询
【发布时间】:2018-11-02 10:54:24
【问题描述】:

在我的 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] 房间插入完成`

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

【问题讨论】:

  • 与其执行SELECT,然后根据结果选择执行INSERTUPDATE,为什么不使用单个INSERT OR REPLACE 语句?请参阅 sqlite.org/lang_insert.html 但这将要求 QMSRoomId 是主键。

标签: ios objective-c performance sqlite


【解决方案1】:

索引会缩短 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? )。另一个优化是在插入大量内容时禁用索引(然后重新启用)。

另一件可能有帮助的事情是拆分更新。如果您只有几个更新,最好单独进行。如果您有很多更新,实际上最好加载完整的表,删除它并从头开始重新加载(不更新)。

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

您应该对这段代码提出一个更一般的建议,即您是否真的需要一次插入 7000 条记录?如果它是来自用户的操作(例如尝试在 UI 中导入一个巨大的数据文件)可能会很好,但是很长一段时间是意料之中的。如果是出于缓存目的,您可以将该缓存保存在内存中,然后将其异步部分地插入到数据库中,这样它就不会影响用户体验。另外对于缓存,我会考虑不完全使用 SQL 数据库,尤其是只读缓存。

【讨论】:

  • 它有帮助。只需将SELECT RoomDesc FROM Room 替换为SELECT QMSRoomId FROM Room 2018-05-24 09:25:00.800 SterileTrakks[918:11014] no of records for Rooms : 7136 2018-05-24 09:25:03.017 SterileTrakks[918:11014] Insertion for Rooms finished
  • 哇,速度是原来的两倍,没想到。
【解决方案2】:

必须使用 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];
    }


}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-20
    • 2010-11-06
    相关资源
    最近更新 更多