【SQLite 3】3_sqlデータバインドメカニズム[共通ベース]

4777 ワード

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
    "); 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 
    #include 
    #include 
    
    int main()
    {
        // 1.      
        sqlite3 *ppdb = NULL;
        int ret = sqlite3_open(":memory:", &ppdb);
        if (ret != SQLITE_OK)
        {
            printf("open fail
    "); 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
    ", 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
    "); break; } sqlite3_free(errmsg); } mingw_gettimeofday(&end, NULL); printf("nsert directly: %ld
    ", 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
    ", end.tv_usec - start.tv_usec); // 3. ret = sqlite3_close(ppdb); if (ret != SQLITE_OK) { printf("close fail
    "); return -1; } return 0; }

    出力:
    nsert directly: 59873
    bind directly: 27925