c++之大數據採用數據切分批量插入數據庫的方法

最近在做一個數據導入功能,數據量爲360W,按照我們通常的比較笨的方法則的遍歷數據一條條的往數據庫插入;經實驗證明這個方法確實可以完成這個工作,但是它的插入數據的速度太慢,尤其當隨着數據庫的數據增加,速度會越來越慢。

所以有的人會說我可以使用事務的方式,確實使用事務的方式可以優化數據的插入速度,一般是可以滿足我們的要求;但是我們知道使用事務,是會導致鎖表的,當執行事務過程中,數據庫會鎖表,導致其它的連接無法操作此表,尤其在服務器端,支持多用戶的情況下,這是一個致命的缺陷;所以現在很多服務器數據庫都是採用分表分庫的方式,使得讀寫分離,可以提高服務器的工作效率。

如果不採用分表分庫的方式我們該怎樣來優化呢?

首先,我們知道一條條插入數據是比較慢的,插入數據批量插入數據才最快。

單條插入:INSERT INTO table_name (列1, 列2,...) VALUES (值1, 值2,....)

批量插入:INSERT INTO table_name (列1, 列2,...) VALUES (值1, 值2,....), (值1, 值2,....), (值1, 值2,....).....

當然批量插入數據有數據量限制,開始我插入360w數據把它們寫入了一條sql語句中,結果導致程序出現段錯誤;

所以我們要限定批量插入數據大小,單次插入多少數據合適,我也不知道,我沒有去查;

我們需要將數據切分成多段然後插入數據庫,切分的方法如下:

std::string AgentRelationNet::getValueListStr(AgentRelationNet mAgentRelationNet) {
	std::ostringstream sql;
	sql	<< "(\'" << mAgentRelationNet.id.toStdString() << "\',"
		<< "\'" << mAgentRelationNet.origId << "\',"
		<< "\'" << mAgentRelationNet.destId << "\')";
	return sql.str();
}

std::list<std::string> AgentRelationNet::getBatchInsertSqlList(std::list<AgentRelationNet> &dataList, long maxLength)
{
	std::list<std::string> sqls;

	if (dataList.size() <= 0)
		return sqls;
	std::string pre = getInsertPre();
	std::ostringstream sqlBuilder;
	sqlBuilder << pre;
	for each (AgentRelationNet mAgentRelationNet in dataList)
	{
		std::string valueStr = AgentRelationNet::getValueListStr(mAgentRelationNet);
		sqlBuilder << valueStr << ",";
	
		if (sqlBuilder.str().length() >= maxLength) {
			std::string sql = sqlBuilder.str();
			sql = sql.substr(0, sql.length() - 1);
			sqls.push_back(sql);
			sqlBuilder.str("");
			sqlBuilder.clear();
			
			sqlBuilder << pre;
		}
	}

	if (sqlBuilder.str().length() > 1) { //處理最後一條或沒有達到最大值時
		std::string sql = sqlBuilder.str();
		sql = sql.substr(0, sql.length() - 1);
		sqls.push_back(sql);
		sqlBuilder.clear();
	}

	return sqls;	
}

std::string AgentRelationNet::getInsertPre() {
	std::ostringstream sql;
	sql << "insert into agent_relation_net(id, orig_agent_id, dest_agent_id) values ";
	return sql.str();
}

總之就是將數據分爲多個批量插入語句,在切分成多個sql語句後,我們可以分幾次插入數庫,在插入語句中我們可以休眠一段時間再執行下一次插入,爲的就是中間騰出一些時間給其它的連接操作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章