提高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到文件
      }
    }
  }

 

posted @ 2022-03-02 15:41  田大叔  阅读(1079)  评论(0编辑  收藏  举报