sql 语句执行流程:剖析 - 编译 - 执行

问题

当执行10000次插入操作时,sql 语句须要被“剖析 - 编译 - 执行”10000次,这是比拟低效的;

  • 示例:
char insert_sql[128] = {0};for (int i=0; i<10000; ++i){    sprintf(insert_sql, "insert into bindtest values(%d, %d)", i, i*100);    ret = sqlite3_exec(ppdb, insert_sql, NULL, NULL, &errmsg);    if (ret != SQLITE_OK)    {        printf("insert fail\n");        break;    }    sqlite3_free(errmsg);}

尝试解决

用绑定机制,能够使 sql 语句只被解析一次,之后的操作应用第一次生成的执行打算,以此带来更高的执行效率。

应用步骤:

配备
int sqlite3_prepare(  sqlite3 *db,            /* Database handle */  const char *zSql,       /* SQL statement, UTF-8 encoded */  int nByte,              /* Maximum length of zSql in bytes. */  sqlite3_stmt **ppStmt,  /* OUT: Statement handle */  const char **pzTail     /* OUT: Pointer to unused portion of zSql */);
绑定数据
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64,                        void(*)(void*));int sqlite3_bind_double(sqlite3_stmt*, int, double);int sqlite3_bind_int(sqlite3_stmt*, int, int);int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);int sqlite3_bind_null(sqlite3_stmt*, int);int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,                         void(*)(void*), unsigned char encoding);int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*,void(*)(void*));int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64);
执行
int sqlite3_step(sqlite3_stmt* mStmt);
如果循环操作(绑定)时
int sqlite3_finalize(sqlite3_stmt *pStmt);
开释
sqlite3_finalize(stmt);
  • 示例:
sqlite3_stmt *pStmt = NULL;char insert[] = "insert into bindtest values(?, ?)";sqlite3_prepare(ppdb, insert, sizeof(insert), &pStmt, NULL);// 2. 绑定数据for (int i=0; i<10000; ++i){    sqlite3_bind_int(pStmt, 1, i);          // 留神这里,绑定从 1 开始 !!!    sqlite3_bind_int(pStmt, 2, i * 100);    sqlite3_step(pStmt);    // 执行插入    sqlite3_reset(pStmt);   // 重置}// 3. 开释sqlite3_finalize(pStmt);

编程试验

#include <stdio.h>#include <sqlite3.h>#include <time.h>int main(){    // 1. 关上数据库    sqlite3 *ppdb = NULL;    int ret = sqlite3_open(":memory:", &ppdb);    if (ret != SQLITE_OK)    {        printf("open fail\n");        return -1;    }    // 2. 执行 sql 语句    // 2.1 创建表格 create table apitest(id int, number int);    const char *create_sql = "create table if not exists bindtest(id int, number int)";    char *errmsg = NULL;    ret = sqlite3_exec(ppdb, create_sql, NULL, NULL, &errmsg);    if (ret != SQLITE_OK)    {        printf("%s\n", errmsg);    }    sqlite3_free(errmsg);    // 2.2 数据直接插入 ==============================    struct timeval start;    struct timeval end;    char insert_sql[128] = {0};    mingw_gettimeofday(&start, NULL);    for (int i=0; i<10000; ++i)    {        sprintf(insert_sql, "insert into bindtest values(%d, %d)", i, i*100);        ret = sqlite3_exec(ppdb, insert_sql, NULL, NULL, &errmsg);        if (ret != SQLITE_OK)        {            printf("insert fail\n");            break;        }        sqlite3_free(errmsg);    }    mingw_gettimeofday(&end, NULL);    printf("nsert directly: %ld\n", end.tv_usec - start.tv_usec);    // 2.3 数据绑定插入 ==============================    sqlite3_stmt *pStmt = NULL;    char insert[] = "insert into bindtest values(?, ?)";    mingw_gettimeofday(&start, NULL);    sqlite3_prepare(ppdb, insert, sizeof(insert), &pStmt, NULL);    for (int i=0; i<10000; ++i)    {        sqlite3_bind_int(pStmt, 1, i);        sqlite3_bind_int(pStmt, 2, i * 100);        sqlite3_step(pStmt);        sqlite3_reset(pStmt);    }    sqlite3_finalize(pStmt);    mingw_gettimeofday(&end, NULL);    printf("bind directly: %ld\n", end.tv_usec - start.tv_usec);    // 3. 敞开数据库    ret = sqlite3_close(ppdb);    if (ret != SQLITE_OK)    {        printf("close fail\n");        return -1;    }    return 0;}

输入:

nsert directly: 59873bind directly: 27925