由于数据量大,直接读Access数据库,速度跟不上,则将表读到sqlite中。
直接从Aceess中读一条,写一条,很慢,6000条数据写了30多分钟。通过sqlite3_prepare_v2方法,稍能提高,但效果不明显。
class DatabaSEOperate
{
private:
_ConnectionPtr m_pConnection;
_RecordsetPtr m_pRecordset;
_variant_t var;
_variant_t RecordsAffected;
std::string name[2];
std::string block[2];
public:
int init()
{
CoInitialize(NULL);
m_pConnection.CreateInstance(__uuidof(Connection));
m_pRecordset.CreateInstance(__uuidof(Recordset));
try
{
m_pConnection->Open(getPath().c_str(),"",adModeUnknown);
return 1;
}
catch(_com_error e)
{
//cout<<"数据库连接失败,确认数据库db1.mdb是否在当前路径下!"<<endl;
return -1;
}
}
int AcsTosql()
{
try
{
std::string sql= "select * from nodeconnect";
m_pRecordset->Open(sql.c_str(),
m_pConnection.GetInterfacePtr(),
adOpenDynamic,
adLockOptimistic,
adCmdText);
if(!m_pRecordset->BOF)
{
m_pRecordset->MoveFirst();
float index=0;
sqlite3_stmt* stmt3 = NULL;
char* cErrMsg;
sqlite3_exec(pDB,"begin;",&cErrMsg);
int ret = sqlite3_prepare_v2(pDB,"insert into NCN(FN,AN,ALEN,CBL) values(?,?,?)",-1,&stmt3,NULL);
if(ret != sqlITE_OK)
{
if(stmt3)
{
sqlite3_finalize(stmt3);
}
m_pRecordset->Close();
m_pRecordset = NULL;
return 0;
}
while(!m_pRecordset->adoEOF)
{
var=m_pRecordset->GetCollect("fnode");
std::string fnode=_com_util::ConvertBSTRToString((_bstr_t)var);
var=m_pRecordset->GetCollect("fsname");
std::string cable=_com_util::ConvertBSTRToString((_bstr_t)var);
var=m_pRecordset->GetCollect("snode");
std::string snode=_com_util::ConvertBSTRToString((_bstr_t)var);
var=m_pRecordset->GetCollect("nodelen");
std::string len=_com_util::ConvertBSTRToString((_bstr_t)var);
/*
string strsql = "";
strsql += "insert into NCN(FN,CBL)";
strsql += "values('";
strsql += fnode;
strsql += "','";
strsql += snode;
strsql += "','";
strsql += len;
strsql += "','";
strsql += cable;
strsql += "');";
cout<<"Now: "<<strsql<<endl;
*/
sqlite3_bind_text(stmt3,1,fnode.c_str(),strlen(fnode.c_str()),NULL);
sqlite3_bind_text(stmt3,2,snode.c_str(),strlen(snode.c_str()),3,len.c_str(),strlen(len.c_str()),4,cable.c_str(),strlen(cable.c_str()),NULL);
if(sqlite3_step(stmt3) != sqlITE_DONE)
{
cout<<"insert fail: "<<endl;
}
/*char* cErrMsg;
int nRes = sqlite3_exec(pDB,strsql.c_str(),&cErrMsg);
if (nRes != sqlITE_OK)
{
cout<<"add user fail: "<<cErrMsg<<endl;
}*/
index=index+1;
cout<<"Now: "<<index<<endl;
sqlite3_reset(stmt3);
m_pRecordset->MoveNext();
}
sqlite3_finalize(stmt3);
sqlite3_exec(pDB,"commit;",&cErrMsg);
m_pRecordset->Close();
m_pRecordset = NULL;
return 1;
}
else
{
m_pRecordset->Close();
m_pRecordset = NULL;
return 0;
}
}
catch(_com_error e)
{
m_pRecordset->Close();
m_pRecordset = NULL;
return -1;
}
}
void conClose()
{
if(m_pConnection->State)
{
m_pConnection->Close();
m_pConnection= NULL;
m_pRecordset = NULL;
}
}
};
原因在sqlite3 insert into 等操作时它是已文件的形式存在磁盘中,每次访问时都要打开一次文件,如果对数据库进行大量的操作,那时很慢。
解决办法用事务的形式提交:因为我们开始事务后,进行的大量操作的语句都保存在内存中,当提交时才全部写入数据库,此时,数据库文件也就只用打开一次。
在进行大量的操作前使用如下语句:
rc = sqlite3_exec(db,&szErrMsg);
for (...)
{
//insert into operate
}
rc = sqlite3_exec(db,&szErrMsg);
这样速度提高了一百多倍,6000多条数据能在2分钟内完成!