【发布时间】:2014-05-28 17:50:42
【问题描述】:
我有一个很大的 SQLite 文件,里面装满了用于创建我的数据库表和插入所有记录的查询。该文件相当大,运行 SQL 文件所需的时间似乎比我预期的要长。
我正在为我正在开发的 iPad 应用程序使用 FMDB,我真的想用新的文件替换当前的数据库文件,但我不确定 sql 文件是否与数据库文件相同。它不包含任何相同的标头信息等...
最好的方法是什么?
【问题讨论】:
标签: objective-c sqlite fmdb
我有一个很大的 SQLite 文件,里面装满了用于创建我的数据库表和插入所有记录的查询。该文件相当大,运行 SQL 文件所需的时间似乎比我预期的要长。
我正在为我正在开发的 iPad 应用程序使用 FMDB,我真的想用新的文件替换当前的数据库文件,但我不确定 sql 文件是否与数据库文件相同。它不包含任何相同的标头信息等...
最好的方法是什么?
【问题讨论】:
标签: objective-c sqlite fmdb
如果使用FMDatabase 进行大量单独的UPDATE 或INSERT 调用,请考虑在开头使用beginTransaction,在结尾使用commit:
[db beginTransaction];
// do all of your updates
[db commit];
或者,如果使用FMDatabaseQueue,请使用inTransaction:
[databaseQueue inTransaction:^(FMDatabase *db , BOOL *rollback) {
// do all of your updates
}];
如果您不使用其中之一,它将在每次插入后提交,这会使其速度变慢。如果添加大量行,差异可能会很大(例如,在添加/更新大量小记录时,我发现性能差异有两个数量级)。
以上假设您正在尝试执行一系列单独的 SQL 命令。如果它们都在一个文件中(例如.dump 输出),FMDB 历史上没有一个接口来执行此操作(即使有一个 SQLite 函数 sqlite3_exec 正是这样做的)。 extra 文件夹最近添加了一个名为 FMDatabaseSplitter 的文件夹,它试图将一长串 SQL 拆分为单独的调用,然后您可以单独调用这些调用。
就个人而言,使用第三方 SQL 解析例程让我很紧张,所以我倾向于直接调用 SQLite 函数sqlite3_exec。为此,您可以使用 FMDB 的sqliteHandle 方法从FMDatabase 对象访问sqlite3 指针,然后直接与sqlite3_exec 函数结合使用:
NSError *error = nil;
NSString *dumpSQL = [NSString stringWithContentsOfFile:dumpFilePath encoding:NSUTF8StringEncoding error:&error];
NSAssert(dumpSQL, @"Loading of SQL failed: %@", error);
int rc = sqlite3_exec(db.sqliteHandle, [dumpSQL UTF8String], NULL, NULL, NULL);
if (rc != SQLITE_OK) {
NSLog(@"sqlite3_exec error: %@", [db lastErrorMessage]);
}
我必须承认,将批量 SQL 导入到应用程序的数据库中让我有点紧张。如果您不非常小心,SQL 中的一个无辜错误可能会破坏整个安装基础的应用程序。我宁愿查看来自服务器的应用程序请求 JSON 或 XML 提要,然后自行进行更新,但如果您想使用 .dump 输出通过 FMDB 更新应用程序的数据库,这是一种方法。
FMDB v2.3 为 sqlite3_exec 引入了一个名为 executeStatements 的包装器:
BOOL success;
NSString *sql = @"create table bulktest1 (id integer primary key autoincrement, x text);"
"create table bulktest2 (id integer primary key autoincrement, y text);"
"create table bulktest3 (id integer primary key autoincrement, z text);"
"insert into bulktest1 (x) values ('XXX');"
"insert into bulktest2 (y) values ('YYY');"
"insert into bulktest3 (z) values ('ZZZ');";
success = [db executeStatements:sql];
【讨论】:
BEGIN TRANSACTION 和 COMMIT 如果通过 SQL 进行,beginTransaction 和 commit 如果使用 FMDB界面)。看到在更新过程中通过使用事务可以实现多少性能改进,这确实是非常令人惊讶的。我是一个实用主义者,所以如果使用 SQL 文件有帮助,那很好,但如果这真的是问题,我会感到惊讶。