在我的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]插入房间完成`
我可以优化此查询插入时间吗?我考虑应用索引,但还有其他方法吗?
答案 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];
}
}
如果有任何查询要放在评论框中。