提高sqlite性能的辦法


  最近有個涉及到對sqlite操作的項目,由於對sqlite數據庫進行頻繁地“寫,讀,查詢”的操作,但是由於查詢這塊每次要取出大概10W條,這樣的耗時就非常大。因為sqlite的數據庫的操作需要加鎖(寫單獨一個線程,讀又是一個線程,查詢又是另一個線程),這樣的話就存在3個線程搶一把鎖,但是因為查詢的數據量又比較多,這時候查詢的話就耗時很嚴重的了,這間接會影響到寫入或者刪除的性能。

  因此網上查了資料,從sqlite的這些參數來入手:synchronous,default_cache_size,page_size,mmap_size,journal_mode這幾個參數來更改。代碼如下:

在SQLConnection.cpp里面的 CSQLConnection::Open這個函數里面的sqlite3_exec 對應的參數更改成如下:

bool SQLITE_SQLCONNECTION_NSAMESPACE::CSQLConnection::Open(const char* szDatabase)

{

  //...................... 

  sqlite3_exec(m_pConnect, "PRAGMA synchronous = OFF;", 0, 0, &zErrMsg);
  sqlite3_exec(m_pConnect, "PRAGMA default_cache_size = 8000;", 0, 0, &zErrMsg);
  sqlite3_exec(m_pConnect, "PRAGMA page_size = 16384;", 0, 0, &zErrMsg);
  sqlite3_exec(m_pConnect, "PRAGMA mmap_size = 4294967296;", 0, 0, &zErrMsg);
  sqlite3_exec(m_pConnect, "PRAGMA journal_mode = WAL;", 0, 0, &zErrMsg);
  //......................

}

  接着,得再把sqlite這使用的數據庫文件match_rpt.db的數據字段加上索引,加上索引之后 ,再進行寫入的壓測。

注意:如果不加索引,性能和CSQLConnection::Open這函數沒有改之前 是一樣的。下面是對進行大量壓測的代碼:  

  {
    string strDelSpMsgid = "3330687908534288664";
    long long nDelMsgId = std::atoll(strDelSpMsgid.c_str());

    string strSpMsgid = "4330687908534288664";
    long long nMsgId = std::atoll(strSpMsgid.c_str());
    time_t tPreTime = time(NULL);
    int iPreCnt = 0;
    for (int iCnt = 0; iCnt < 3000000; ++iCnt)
    {
      string strSpMsgid = cstr::format("%lld", nMsgId++);
      strMobiles = cstr::format("13801%06d", iCnt);
      WritetoSqlite(strMobiles, nType, strSpMsgid);        //寫數據到sqlite
      time_t tNowTime = time(NULL);
      if (tPreTime != tNowTime)
      {
        string ResponseInfo = cstr::format("速度:%d /s, 總數: %d", iCnt - iPreCnt, iCnt);   
        CSmsTools::GetInstance().WriteLogMsg(ResponseInfo.c_str(), ResponseInfo.size(), CSmsTools::LOG_LEVEL_WARNING);   //寫入文件
        iPreCnt = iCnt;
        tPreTime = tNowTime;
      }

    }
  }

  用上面的這段代碼測試(壓測300W條數據),match_rpt.db加了索引的話就有4000-8000條的數據,但是不加索引 的話,就300-500條左右每秒;這些數據對應的就是sqlite的性能。。。

 

附注WritetoSqlite的實現:

        #define WRITE_MT "insert into match_queue(phone,sendtime,productid,spmsgid,defeated)values('%s',%d,%d,'%s',%d)"

  void WritetoSqlite(string &strPhone, int productid, string &spmsgid, int nDefeated=0)
  {
    time_t tNow = time(NULL) + m_nQueWitTime * 60;         //m_nQueWitTime的值固定為5
    char szSql[512] = "0";
    std::vector<std::string> vecMobiles;
    CSmsTools::SplitStringToArray(strPhone, ",", vecMobiles, false);     //將電話號碼一個個拆分出來,以","來分隔
    for (auto& ite : vecMobiles)
    {
      lock_guard<mutex> lock_tmp(m_LockMatchMt);          //執行寫入數據進sqlite時需要加鎖
      sprintf_s(szSql, sizeof(szSql)-1, WRITE_MT, ite.c_str(), tNow, productid, spmsgid.c_str(), nDefeated);
      std::string strErrMsg = ""; std::string strErrDesc = "";
      int nError = sqlite_helper.ExecuteSqliteCmd(strErrMsg, strErrDesc, szSql);
      if (strErrMsg.compare("SUCCESS") != 0)
      {
        string strInfo = cstr::format("寫入數據異常 %s,錯誤原因%s -%s \r\n", szSql, strErrDesc.c_str(), strErrMsg.c_str());
        CSmsTools::GetInstance().WriteLogMsg(strInfo.c_str(), strInfo.length(), CSmsTools::LOG_LEVEL_ERROR);       //打印log到文件
      }
    }
  }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM