有人能解释一下使用FMDB在iPhone上插入大量数据的最佳方法是什么?我看到使用beginTransaction命令之类的东西.老实说,我不确定这个或setShouldCacheStatements是做什么的.我按照我的同事到目前为止所做的代码,这就是它的样子:
BOOL oldshouldcachestatements = _db.shouldCacheStatements;
[_db setShouldCacheStatements:YES];
[_db beginTransaction];
NSString *insertQuery = [[NSString alloc] initWithFormat:@"INSERT INTO %@ values(null, ?, ?, ?, ?, ?, ?, ?);", tableName];
[tableName release];
BOOL success;
bPtr += 2;
int *iPtr = (int *)bPtr;
int numRecords = *iPtr++;
for (NSInteger record = 0; record < numRecords; record++) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Some business logic to read the binary stream
NSNumber *freq = aFreq > 0 ? [NSNumber numberWithDouble:100 * aFreq / 32768]: [NSNumber numberWithDouble:-1.0];
// these fields were calculated in the business logic section
success = [_db executeUpdate:insertQuery,
cID,
[NSNumber numberWithInt:position],
[NSString stringWithFormat:@"%@%@", [self stringForTypeA:typeA], [self stringForTypeB:typeB]], // methods are switch statements that look up the decimal number and return a string
[NSString stringWithFormat:@"r%i", rID],
[self stringForOriginal:original],
[self stringForModified:modified],
freq];
[pool drain];
}
[outerPool drain];
[_db commit];
[_db setShouldCacheStatements:oldshouldcachestatements];
Run Code Online (Sandbox Code Playgroud)
这是我能做的最快的吗?写作是sqlite的限制吗?我看到了这个:http://www.sqlite.org/faq.html#q19并且不确定这个实现是否与fmdb最好,或者我还能做其他任何事情.其他一些同事提到了关于批量插入和优化的一些内容,但我不确定这是什么意思,因为这是我的第一次sqlite遭遇.我可以去研究任何想法或方向吗?谢谢!
Seb*_*jas 38
首先,在大多数情况下,如果您没有完全错误地使用它,则不必担心sqlite3的性能.
以下事项提高了INSERT语句的性能:
交易
正如您已经提到的,交易是最重要的功能.特别是如果你有大量的查询,交易将加速你的INSERTs约10倍.
PRAGMA配置
Sqlite3提供了几种机制,可以避免在最糟糕的情况下数据库损坏.在某些情况下,这不是必需的.在其他方面,这绝对是必不可少的.以下sqlite3命令可以加快您的INSERT语句.您的应用程序的正常崩溃不会破坏数据库,但操作系统崩溃可能会.
PRAGMA synchronous=OFF -- may cause corruption if the OS fails
PRAGMA journal_mode=MEMORY -- Insert statements will be written to the disk at the end of the transaction
PRAGMA cache_size = 4000 -- If your SELECTs are really big, you may need to increase the cache
PRAGMA temp_store=MEMORY -- Attention: increases RAM use
Run Code Online (Sandbox Code Playgroud)
停用指示
任何SQL索引都会降低INSERT语句速度.检查你的表是否有一些索引:
.indices <table_name>
Run Code Online (Sandbox Code Playgroud)
如果是的话,删除INDEX和CREATE交易后.
一选
在生成新数据时,我没有看到使用BULK插入的方法.但是,您可以收集数据并只执行一个INSERT语句.这可能会大大提高您的性能,但也会增加失败的可能性(例如语法).一个hack遇到另一个hack:由于sqlite3不直接支持这个,你必须使用UNION命令相应地收集所有insert语句.
INSERT INTO 'tablename'
SELECT 'data1' AS 'column1', 'data2' AS 'column2'
UNION SELECT 'data3', 'data4'
UNION SELECT 'data5', 'data6'
UNION SELECT 'data7', 'data8'
Run Code Online (Sandbox Code Playgroud)
声明缓存
我建议避免使用语句缓存,因为这个功能存在一个未修复的问题(据我所知,它并没有显着影响性能).
内存管理
我想提到的最后一点是关于ObjC.与基本操作相比,内存管理需要非常多的时间.也许你可以避免一些stringWithFormat:或numberWithDouble:在循环外准备这些变量.
摘要
总而言之,如果你只是简单地使用交易,我认为你不会对sqlite3的速度有任何问题.
我发现很难找到一个关于如何快速插入很多行的具体代码示例.经过FMDB的大量实验和上面答案的帮助,这就是我现在正在使用的内容:
[_objectController.dbQueue inDatabase:^(FMDatabase *db)
{
[db open];
[db setShouldCacheStatements:YES];
NSArray *documentsJSONStream = responseObject[@"details"][@"stream"];
static NSString *insertSQLStatment = @"INSERT INTO documents (`isShared`,`thumbnailURLString`,`userID`,`version`,`timestamp`,`tags`,`title`,`UDID`,`username`,`documentURLString`,`shareURLString`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
[db beginTransaction];
for (NSDictionary *dJ in documentsJSONStream)
{
[db executeUpdate:insertSQLStatment withArgumentsInArray:@[dJ[@"isShared"],dJ[@"thumbnailURLString"],dJ[@"userID"],dJ[@"version"],dJ[@"timestamp"],dJ[@"tags"],dJ[@"title"],dJ[@"UDID"],dJ[@"username"],dJ[@"documentURLString"],dJ[@"shareURLString"]]];
}
[db commit];
[db close];
}];
Run Code Online (Sandbox Code Playgroud)
使用inTransaction给了我奇怪的FMDB没有打开错误.如果有任何关于如何改进的建议,请告诉我.
| 归档时间: |
|
| 查看次数: |
8241 次 |
| 最近记录: |