SQLite替代SELECT,然后插入一组100万条记录中的每条记录

时间:2015-03-23 07:06:26

标签: c database sqlite

我正在创建一个应用程序,其中数据被传输到包含2个表的数据库,而对于主表,我需要检查我尝试插入的记录是否已经存在。

如果找到记录,则其Id用于与要存储在第二个表中的记录一起存储。 如果在第一个表中找不到记录,则会创建一个新条目,并将新记录的id与第二个表中的数据一起存储

我在每次插入前执行select时遇到问题,如果记录存在,则获取现有ID。

  1. 如果我索引要搜索的列,则会以指数方式降低插入速度。十万条记录之后。
  2. 如果我没有索引要搜索的列,它仍然需要花费很多时间。
  3. 如果没有选择直接插入,插入所有记录所需的时间为10秒--12秒。
  4. 所以我需要帮助,如何提高我的任务速度
  5. 到目前为止,我已经提到了这些链接,但这只是帮助我提高插入速度但是当我使用select时减慢速度 Improve INSERT-per-second performance of SQLite?

    我想过使用INSERT OR IGNORE检查记录是否存在,如果没有将它插入数据库,但即使在这种情况下也要获取记录的Id我需要做一个选择

    使用代码:

    int TransferUrls(int numberOfEntries, PCHAR dbName, PCHAR urlList)
    {
    sqlite3      *dbHandle              = NULL; 
    int          returnCode             = 0;
    int          mainTableEntryNumber   = 0;
    int          processedUrlId         = 0;
    int          returnCode1            = 0;
    sqlite3_stmt *selectIdStatement     = NULL;
    sqlite3_stmt *insertProcessedUrl    = NULL;
    sqlite3_stmt *insertRawUrl          = NULL;
    int          numberOfEntriesRead    = 0;
    clock_t      cStartClock;
    WCHAR        rawUrl[MAX_URL_LENGTH] = L"";
    CHAR         processedUrl[MAX_URL_LENGTH] = "";
    CHAR         url[MAX_URL_LENGTH] = "";
    int          status = 0;
    FILE         *fp = NULL;
    errno_t      err;
    
    memset(rawUrl, '\0', sizeof(rawUrl));
    memset(processedUrl, '\0', sizeof(processedUrl));   
    memset(url , '\0', sizeof(url));
    
    //open the file from which we are goin to read the links
    err = fopen_s(&fp, urlList, "r");
    if(err != 0)
    {
        printf("Error opening the file to transfer urls to databse\n");
        return TRANSFER_ERROR;
    }
    
    //open a connection to the database in which we would have to enter
    returnCode = sqlite3_open(dbName, &dbHandle);
    
    if(returnCode != SQLITE_OK)
    {
        printf("Error occured while opening database \n");
        return TRANSFER_ERROR;
    }
    
    //Get the idNo from the MainTable, used for some calculation , ignore it
    if(getLastIdNumber(dbHandle, mainTableEntryNumber) == ERROR)
    {
        fclose(fp);
        sqlite3_close(dbHandle);
        return TRANSFER_ERROR;
    }       
    
    //Create a prepared statement to get entry number for an processed url
    returnCode = sqlite3_prepare_v2(dbHandle, "SELECT idNo FROM urlDetails  where processedUrl = ?;", -1, &selectIdStatement, NULL);
    if(returnCode != SQLITE_OK)
    {
        printf("Error occured while preparing select statement for getting idNo\n");
        printf("Error msg : %s \n", sqlite3_errmsg(dbHandle));
        fclose(fp);
        sqlite3_close(dbHandle);
        return TRANSFER_ERROR;
    }
    
    //create prepared statememnt to insert entry in main table for the processed url
    returnCode = sqlite3_prepare_v2(dbHandle, "INSERT INTO urlDetails(idNo, processedUrl, insertTime) VALUES(?, ?, datetime('now','unixepoch', 'localtime'));", -1, &insertProcessedUrl, NULL);
    if(returnCode != SQLITE_OK)
    {
        printf("Error occured wile preparing insert statement to insert values for processed url\n");
        printf("Error msg: %s\n", sqlite3_errmsg(dbHandle));
        sqlite3_finalize(selectIdStatement);
        fclose(fp);
        sqlite3_close(dbHandle);
        return TRANSFER_ERROR;
    }
    
    returnCode = sqlite3_prepare_v2(dbHandle, "INSERT INTO urlData VALUES(?, ?);", -1, &insertRawUrl, NULL);
    if(returnCode != SQLITE_OK)
    {
        printf("Error occured wile preparing insert statement to insert values for raw url\n");
        printf("Error msg: %s\n", sqlite3_errmsg(dbHandle));
        sqlite3_finalize(selectIdStatement);
        sqlite3_finalize(insertProcessedUrl);
        fclose(fp);
        sqlite3_close(dbHandle);
        return TRANSFER_ERROR;
    }
    
    
    //make synchronous mode off
    returnCode = sqlite3_exec(dbHandle, "PRAGMA synchronous = OFF;", NULL, NULL,NULL);
    if(returnCode != SQLITE_OK)
    {
        printf("Error occured while making pragma synchronous mode off\n");
        status = TRANSFER_ERROR;
        goto EXIT;  
    }
    
    //make journal_mode to memory
    returnCode = sqlite3_exec(dbHandle, "PRAGMA journal_mode = OFF;", NULL, NULL,NULL);
    if(returnCode != SQLITE_OK)
    {
        printf("Error occured while making pragma jorunal mode to memory\n");
        status = TRANSFER_ERROR;
        goto EXIT;
    }
    
    returnCode = sqlite3_exec(dbHandle,"BEGIN TRANSACTION;", NULL , NULL , NULL);
    if(returnCode != SQLITE_OK)
    {
        printf("Error occured while making pragma synchronous mode off\n");
        status = TRANSFER_ERROR;
        goto EXIT;
    }   
    
    // get the number of seconds since the program was run
    cStartClock = clock();
    
    int entryNumber = 0;
    //Read data from a table which consists of raw url and insert the data in both the tables urlData and urlDetails based on conditions
    while(fgets(url, MAX_URL_LENGTH, fp) != NULL)
    {
        entryNumber++;
    
        //check for the number of entries
        if(entryNumber == numberOfEntries)
        {
            break;              
        }
        else
        {
            memset(rawUrl, '\0', sizeof(rawUrl));
    
            //Replace the trailing newline character in string with string terminating character
            size_t len = strlen(url);
    
            if (len > 0 && url[len-1] == '\n') 
            {
                url[--len] = '\0';
            }
    
            //printf("Entry %d : %s\n",entryNumber,  url);
    
            numberOfEntriesRead++;  
    
            //printf("Url is  %s \n", url);
    
            //getting the name for the rawUrl
            if(swprintf_s(rawUrl, MAX_URL_LENGTH, L"http://%S", url) == -1)
            {
                printf("Error occured while preparing raw url for %s \n", url);
                continue;
            }
            //here we will perform the further operation i.e give a task to the user i.e get the processed url
            if(getUrlDetails(rawUrl, processedUrl) == GET_URL_ERROR)
            {
                printf("Error occured while gettting processed url from %s raw url\n", rawUrl);
                continue;
            }
    
            //1. check for the url in the database 
            //2. If present then store its id number and make an entry for the raw url
            //3. if not present then store the id number for the proceesed url ,and make entry for both processed and raw url
            returnCode = sqlite3_bind_text(selectIdStatement, 1, processedUrl, -1, NULL);
            if(returnCode != SQLITE_OK)
            {
                printf("Error occcured while binding for select Id statement for url %s\n", processedUrl);
                printf("Error msg : %s \n",sqlite3_errmsg(dbHandle));
                status = TRANSFER_ERROR;
                break;
            }
    
            returnCode = sqlite3_step(selectIdStatement);
            if(returnCode == SQLITE_ROW)
            {
                //this indicates that the processed url is already present in the database
                processedUrlId = sqlite3_column_int(selectIdStatement, 0);
    
            }
            else if (returnCode == SQLITE_DONE)
            {
                mainTableEntryNumber++;
    
                processedUrlId = mainTableEntryNumber;
    
                //make an entry for the processed url in the table
                //bind values to insert statement to set the idNumber
                returnCode = sqlite3_bind_int(insertProcessedUrl, 1, processedUrlId);
                if(returnCode != SQLITE_OK)
                {
                    printf("Error occured while binding select statement for insert statement \n");
                    status = TRANSFER_ERROR;
                    break;
                }
    
                //bind the name of the proceesed url to the insert statement for making a new entry in Main table
                returnCode = sqlite3_bind_text(insertProcessedUrl, 2, processedUrl, -1, NULL);
                if(returnCode != SQLITE_OK)
                {
                    printf("Error occured while binding select statement for insert statement \n");
                    status = TRANSFER_ERROR;
                    break;
                }
    
                //execute the insert statement
                returnCode = sqlite3_step(insertProcessedUrl);
                if(returnCode != SQLITE_DONE)
                {
                    printf("Error occured while insert entry into the new table \n");
                    printf("Error msg: %s\n", sqlite3_errmsg(dbHandle));
                    status = TRANSFER_ERROR;
                    break;
                }
    
                sqlite3_reset(insertProcessedUrl);
            }
            else if (returnCode == SQLITE_ERROR)
            {
                printf("Error occured while fetching data for processed url %s\n", processedUrl);
                status = TRANSFER_ERROR;
                break;
            }
    
            //make an entry for the raw url into the other table
            sqlite3_bind_text(insertRawUrl, 1, url,-1, NULL); 
            sqlite3_bind_int(insertRawUrl, 2, processedUrlId);
    
            returnCode = sqlite3_step(insertRawUrl);
            if(returnCode != SQLITE_DONE)
            {
                printf("Error occured while inserting an entry for the raw url \n");
                printf("Error msg : %s\n", sqlite3_errmsg(dbHandle));
                status = TRANSFER_ERROR;
                break;
            }
            sqlite3_reset(insertRawUrl);
            sqlite3_reset(selectIdStatement);
        }   
    
        memset(url, '\0', sizeof(url));
    }
    
    //Calculate the number of seconds required for the program to complete
    printf("%d Entries were processed in %4.6f seconds\n", numberOfEntriesRead, (clock() - cStartClock)/(double)CLOCKS_PER_SEC);
    
    sqlite3_exec(dbHandle,"END TRANSACTION;", NULL , NULL , NULL);
    
    
    
        //free the memory allocated for the select statement as we are done with it
    EXIT :  sqlite3_finalize(selectIdStatement);
            sqlite3_finalize(insertProcessedUrl);
            sqlite3_finalize(insertRawUrl);
    
            //Close the handle to the database connection
            sqlite3_close(dbHandle);
    
            //close the handle to file
            fclose(fp);
    
            return status;
    }
    

0 个答案:

没有答案