我听说使用SQLite的预准备语句可以提高性能。我写了一些代码来测试这一点,并没有看到使用它们在性能上的任何差异。所以,我想也许我的代码是不正确的。如果你在我的操作中发现任何错误,请让我知道...
[self testPrep:NO dbConn:dbConn];
[self testPrep:YES dbConn:dbConn];
reuse=0
recs=2000
2009-11-09 10:39:18 -0800
processing...
2009-11-09 10:39:32 -0800
reuse=1
recs=2000
2009-11-09 10:39:32 -0800
processing...
2009-11-09 10:39:46 -0800
-(void)testPrep:(BOOL)reuse dbConn:(sqlite3*)dbConn{
int recs = 2000;
NSString *sql;
sqlite3_stmt *stmt;
sql = @"DROP TABLE test";
sqlite3_exec(dbConn, [sql UTF8String],NULL,NULL,NULL);
sql = @"CREATE TABLE test (id INT,field1 INT, field2 INT,field3 INT,field4 INT,field5 INT,field6 INT,field7 INT,field8 INT,field9 INT,field10 INT)";
sqlite3_exec(dbConn, [sql UTF8String],NULL,NULL,NULL);
for(int i=0;i<recs;i++){
sql = @"INSERT INTO test (id,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10) VALUES (%d,1,2,3,4,5,6,7,8,9,10)";
sqlite3_exec(dbConn, [sql UTF8String],NULL,NULL,NULL);
}
sql = @"BEGIN";
sqlite3_exec(dbConn, [sql UTF8String],NULL,NULL,NULL);
if (reuse){
sql = @"select * from test where field1=?1 and field2=?2 and field3=?3 and field4=?4 and field5=?5 and field6=?6 and field6=?6 and field8=?8 and field9=?9 and field10=?10 and id=?11";
sqlite3_prepare_v2(dbConn, [sql UTF8String], -1, &stmt, NULL);
}
NSLog(@"reuse=%d",reuse);
NSLog(@"recs=%d",recs);
NSDate *before = [NSDate date];
NSLog([before description]);
NSLog(@"processing...");
for(int i=0;i<recs;i++){
if (!reuse){
sql = @"select * from test where field1=?1 and field2=?2 and field3=?3 and field4=?4 and field5=?5 and field6=?6 and field6=?6 and field8=?8 and field9=?9 and field10=?10 and id=?11";
sqlite3_prepare_v2(dbConn, [sql UTF8String], -1, &stmt, NULL);
}
sqlite3_bind_int(stmt, 1, 1);
sqlite3_bind_int(stmt, 2, 2);
sqlite3_bind_int(stmt, 3, 3);
sqlite3_bind_int(stmt, 4, 4);
sqlite3_bind_int(stmt, 5, 5);
sqlite3_bind_int(stmt, 6, 6);
sqlite3_bind_int(stmt, 7, 7);
sqlite3_bind_int(stmt, 8, 8);
sqlite3_bind_int(stmt, 9, 9);
sqlite3_bind_int(stmt, 10, 10);
sqlite3_bind_int(stmt, 11, i);
while(sqlite3_step(stmt) == SQLITE_ROW) {
}
sqlite3_reset(stmt);
}
sql = @"BEGIN";
sqlite3_exec(dbConn, [sql UTF8String],NULL,NULL,NULL);
NSDate *after = [NSDate date];
NSLog([after description]);
}发布于 2009-11-10 03:35:37
预准备语句通过在query optimizer找到最佳计划后缓存execution plan for a query来提高性能。
如果您正在使用的查询没有复杂的计划(比如没有连接的简单selects/inserts ),那么准备好的语句不会给您带来很大的改进,因为优化器会很快找到最佳计划。
但是,如果您对具有几个连接并使用了一些索引的查询运行相同的测试,您将看到性能差异,因为优化器不会在每次执行查询时都运行。
发布于 2009-12-08 02:18:34
是的-无论你是使用sqlite3_exec()还是sqlite3_prepare_v2() / sqlite3_bind_xxx() / sqlite3_step()进行批量插入,都会有很大的不同。
sqlite3_exec()只是一种方便的方法。在内部,它只是调用相同的sqlite3_prepare_v2() and sqlite3_step()序列。您的示例代码在文字字符串上反复调用sqlite3_exec():
for(int i=0;i<recs;i++){
sql = @"INSERT INTO test (id,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10) VALUES (%d,1,2,3,4,5,6,7,8,9,10)";
sqlite3_exec(dbConn, [sql UTF8String],NULL,NULL,NULL);
}我不知道SQLite解析器的内部工作原理,但也许解析器足够智能,能够识别出您正在使用相同的文字字符串,然后跳过每次迭代的重新解析/重新编译。
如果您尝试对更改的值进行相同的实验-您将看到性能上的更大差异。
发布于 2011-08-16 21:27:58
使用prepare + step而不是execute可以极大地提高性能。在某些情况下,执行时间的性能增益超过100%。
https://stackoverflow.com/questions/1703203
复制相似问题