主要为了看一下,多个进程多表对SQL进行操作和单进程对单个表进行写数据的效率问题。 3次测试出来的数据如下 主console程序(由此进程创建21个进程) table1——table20为20个进程对20个表分别写1万条记录 table总为单进程对1个表写20万条记录 所有表中只有1个为name的char字段 数据如下 第一次: 主console程序开始时间:21分25秒 table6开始时间:21分25秒 table5开始时间:21分25秒 主console程序结束时间:21分25秒 table1开始时间:21分25秒 table2开始时间:21分25秒 table总开始时间:21分25秒 table8开始时间:21分25秒 table3开始时间:21分25秒 table4开始时间:21分26秒 table7开始时间:21分26秒 table9开始时间:21分26秒 table10开始时间:21分26秒 table12开始时间:21分26秒 table13开始时间:21分26秒 table11开始时间:21分26秒 table15开始时间:21分26秒 table18开始时间:21分26秒 table17开始时间:21分26秒 table19开始时间:21分27秒 table14开始时间:21分27秒 table20开始时间:21分27秒 table16开始时间:21分27秒 table18结束时间:22分41秒 table19结束时间:22分41秒 table14结束时间:22分41秒 table1结束时间:22分41秒 table3结束时间:22分42秒 table17结束时间:22分42秒 table2结束时间:22分42秒 table9结束时间:22分42秒 table20结束时间:22分42秒 table6结束时间:22分42秒 table13结束时间:22分59秒 table5结束时间:23分0秒 table16结束时间:23分0秒 table8结束时间:23分0秒 table7结束时间:23分0秒 table11结束时间:23分0秒 table10结束时间:23分1秒 table12结束时间:23分1秒 table15结束时间:23分1秒 table4结束时间:23分1秒 table总结束时间:24分41秒 第二次: 主console程序开始时间:27分48秒 table9开始时间:27分48秒 table2开始时间:27分48秒 table3开始时间:27分48秒 主console程序结束时间:27分48秒 table总开始时间:27分48秒 table5开始时间:27分49秒 table1开始时间:27分49秒 table6开始时间:27分49秒 table7开始时间:27分49秒 table8开始时间:27分49秒 table4开始时间:27分49秒 table12开始时间:27分49秒 table10开始时间:27分50秒 table13开始时间:27分50秒 table15开始时间:27分50秒 table16开始时间:27分50秒 table18开始时间:27分50秒 table14开始时间:27分50秒 table19开始时间:27分50秒 table11开始时间:27分50秒 table17开始时间:27分50秒 table20开始时间:27分50秒 table3结束时间:28分52秒 table9结束时间:28分53秒 table5结束时间:29分0秒 table12结束时间:29分2秒 table16结束时间:29分2秒 table19结束时间:29分2秒 table14结束时间:29分3秒 table17结束时间:29分3秒 table13结束时间:29分3秒 table4结束时间:29分3秒 table7结束时间:29分3秒 table2结束时间:29分11秒 table6结束时间:29分15秒 table11结束时间:29分15秒 table18结束时间:29分16秒 table8结束时间:29分16秒 table20结束时间:29分16秒 table10结束时间:29分17秒 table1结束时间:29分17秒 table15结束时间:29分17秒 table总结束时间:31分2秒
第三次: 主console程序开始时间:32分17秒 table12开始时间:32分17秒 主console程序结束时间:32分17秒 table17开始时间:32分17秒 table2开始时间:32分18秒 table3开始时间:32分18秒 table1开始时间:32分18秒 table总开始时间:32分18秒 table7开始时间:32分18秒 table6开始时间:32分18秒 table5开始时间:32分18秒 table4开始时间:32分18秒 table10开始时间:32分18秒 table8开始时间:32分18秒 table9开始时间:32分18秒 table11开始时间:32分18秒 table13开始时间:32分18秒 table16开始时间:32分19秒 table20开始时间:32分19秒 table15开始时间:32分19秒 table14开始时间:32分19秒 table18开始时间:32分19秒 table19开始时间:32分19秒 table17结束时间:33分19秒 table2结束时间:33分24秒 table1结束时间:33分28秒 table10结束时间:33分29秒 table20结束时间:33分30秒 table9结束时间:33分30秒 table6结束时间:33分31秒 table14结束时间:33分31秒 table11结束时间:33分31秒 table18结束时间:33分31秒 table13结束时间:33分31秒 table12结束时间:33分36秒 table3结束时间:33分41秒 table5结束时间:33分43秒 table16结束时间:33分43秒 table7结束时间:33分43秒 table4结束时间:33分43秒 table19结束时间:33分44秒 table15结束时间:33分44秒 table8结束时间:33分44秒 table总结束时间:35分40秒
从数据可以看出来,21个进程同时写40万条记录大约需要3分钟多点的时间。 20个进程同时写的时间只比1个进程写快2分钟左右,当然这样测试是很不准确的,因为21个进程同时开,那单独写20万数据的进程所分配到的CPU时间片是很少的。 机器为512M,2.4G 也可以测试其它方面的,只要把程序稍微改动一下就可以。 程序B主控,程序A是用来开20个进程的,程序C是用来开1个进程的。
代码我都贴在下面 // DataAccess.h: interface for the CDataAccess class. // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_DATAACCESS_H__BE165B0F_3E92_44BC_9C3B_6F4CC36AD153__INCLUDED_) #define AFX_DATAACCESS_H__BE165B0F_3E92_44BC_9C3B_6F4CC36AD153__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include <assert.h> #include <iostream> #include <string> using namespace std;
#define READ_ONLY 1 #define WRITE_ONLY 2 #define READ_WRITE 3
template<typename Container, typename ValueType, int nPropType> class CProperty { public: CProperty() { m_cObject = NULL; Set = NULL; Get = NULL; } //设置属性所在的对象指针 void setContainer(Container* cObject) { m_cObject = cObject; } //设置set指针,用来修改属性用 void setter(void (Container::*pSet)(ValueType value)) { if((nPropType == WRITE_ONLY) || (nPropType == READ_WRITE)) Set = pSet; else Set = NULL; } //设置get指针,用来读取属性用 void getter(ValueType (Container::*pGet)()) { if((nPropType == READ_ONLY) || (nPropType == READ_WRITE)) Get = pGet; else Get = NULL; } //重载=操作符,用于实现这样的操作 CAdoConnection.Connected = TRUE; //注意CAdoConnection.Connected其实是一个CProperty的对象 //属性的实现关键在于重载=操作符和隐式转换操作符 //重载后调用CProperty的拥有者的get、set函数来达到目的 ValueType operator =(const ValueType& value) { assert(m_cObject != NULL); assert(Set != NULL); (m_cObject->*Set)(value); return value; } //重载隐式转换操作符 operator ValueType() { assert(m_cObject != NULL); assert(Get != NULL); return (m_cObject->*Get)(); } private: Container* m_cObject; //属性的拥有者 void (Container::*Set)(ValueType value); //set函数指针 ValueType (Container::*Get)(); //get函数指针 }; class CAdoConnection { public: CAdoConnection(); ~CAdoConnection(); //隐式的转换操作,不推荐使用,只是暂时类没有封装好,给客户一个方便 //使用时请确保指针在类的生命期内使用 operator _ConnectionPtr(); public: CProperty<CAdoConnection, BOOL, READ_WRITE> Connected; string ConnectingString; string UserName, PassWord; private: void SetConnected(BOOL ConnectFlag); BOOL GetConnected(); private: _ConnectionPtr m_ptrConn; friend class CAdoCommand; friend class CAdoQuery; };
class CAdoCommand { public: CAdoCommand(); ~CAdoCommand(); void Execute(); operator _CommandPtr();
public: CommandTypeEnum CommandType; string CommandText; CAdoConnection * m_AdoConnection; private: _CommandPtr m_ptrComm; }; class CAdoQuery { public: CAdoQuery(); ~CAdoQuery(); void Open(); operator _RecordsetPtr(); public: string Sql; CAdoConnection * m_AdoConnection; private: _RecordsetPtr m_ptrRec; }; #endif // !defined(AFX_DATAACCESS_H__BE165B0F_3E92_44BC_9C3B_6F4CC36AD153__INCLUDED_)
// DataAccess.cpp: implementation of the CDataAccess class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "DataAccess.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// //CAdoConnection CAdoConnection::CAdoConnection() { Connected.setContainer(this); Connected.setter(&CAdoConnection::SetConnected); Connected.getter(&CAdoConnection::GetConnected); // 创建一个连接实例 try { HRESULT hr = m_ptrConn.CreateInstance(__uuidof(Connection)); if (FAILED(hr)) { CString errormessage("创建实例失败!"); AfxMessageBox(errormessage); throw; } } catch(_com_error & error) { CString errormessage; errormessage.Format("创建实例失败!\r\n错误信息:%s", error.ErrorMessage()); AfxMessageBox(errormessage); } // 设定连接等待的最大秒数,默认是15秒 m_ptrConn->ConnectionTimeout=15; UserName = ""; PassWord = ""; } CAdoConnection::~CAdoConnection() { if (GetConnected()) SetConnected(FALSE); m_ptrConn=NULL; } CAdoConnection::operator _ConnectionPtr() { return m_ptrConn; } void CAdoConnection::SetConnected(BOOL ConnectFlag) { if (TRUE == ConnectFlag) { try { // 打开连接 m_ptrConn->Open(ConnectingString.c_str(), UserName.c_str(), PassWord.c_str(), adModeUnknown); } catch(_com_error & error) { CString errormessage; errormessage.Format("连接数据库失败!\r\n错误信息:%s", error.ErrorMessage()); AfxMessageBox(errormessage); } } else { m_ptrConn->Close(); } } BOOL CAdoConnection::GetConnected() { if (m_ptrConn->State == adStateOpen) return TRUE; else return FALSE; } //CAdoCommand CAdoCommand::CAdoCommand() { m_AdoConnection = NULL; CommandText = adCmdText; // 创建一个命令对象实例 try { HRESULT hr = m_ptrComm.CreateInstance(__uuidof(Command)); if (FAILED(hr)) { CString errormessage("创建实例失败!"); AfxMessageBox(errormessage); throw; } } catch(_com_error & error) { CString errormessage; errormessage.Format("创建实例失败!\r\n错误信息:%s", error.ErrorMessage()); AfxMessageBox(errormessage); } } CAdoCommand::~CAdoCommand() { m_ptrComm = NULL; }
void CAdoCommand::Execute() { if ((m_AdoConnection == NULL) || (m_AdoConnection->Connected == FALSE)) return; m_ptrComm->ActiveConnection = m_AdoConnection->m_ptrConn; m_ptrComm->CommandType = CommandType; m_ptrComm->CommandText = CommandText.c_str(); try { m_ptrComm->Execute(NULL,NULL,adCmdUnknown); } catch(_com_error & error) { CString errormessage; errormessage.Format("查询数据库失败!\r\n错误信息:%s", error.ErrorMessage()); AfxMessageBox(errormessage); } } CAdoCommand::operator _CommandPtr() { return m_ptrComm; } //CAdoQuery CAdoQuery::CAdoQuery() { m_AdoConnection = NULL; // 创建一个_RecordsetPtr对象实例 try { HRESULT hr = m_ptrRec.CreateInstance("ADODB.Recordset"); if (FAILED(hr)) { CString errormessage("创建实例失败!"); AfxMessageBox(errormessage); throw; } } catch(_com_error & error) { CString errormessage; errormessage.Format("创建实例失败!\r\n错误信息:%s", error.ErrorMessage()); AfxMessageBox(errormessage); } } CAdoQuery::~CAdoQuery() { m_ptrRec = NULL; }
void CAdoQuery::Open() { if ((m_AdoConnection == NULL) || (m_AdoConnection->Connected == FALSE)) return; try { m_ptrRec->Open(Sql.c_str(), (m_AdoConnection->m_ptrConn).GetInterfacePtr(), adOpenDynamic, adLockOptimistic, adCmdText); } catch(_com_error & error) { CString errormessage; errormessage.Format("查询数据库失败!\r\n错误信息:%s", error.ErrorMessage()); AfxMessageBox(errormessage); } } CAdoQuery::operator _RecordsetPtr() { return m_ptrRec; } // a.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "a.h" #include "DataAccess.h" #include <fstream> using namespace std; #ifdef _DEBUG #define new DEBUG_NEW #endif // 唯一的应用程序对象
CWinApp theApp; using namespace std; int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0; ofstream file("test.txt",std::ios::app); CTime ct; CString text; ct = CTime::GetCurrentTime(); text.Format("%d分%d秒", ct.GetMinute(), ct.GetSecond()); file << argv[1] << "开始时间:" << text << endl; CoInitialize(NULL); // 初始化 MFC 并在失败时显示错误 if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) { // TODO: 更改错误代码以符合您的需要 _tprintf(_T("致命错误: MFC 初始化失败\n")); nRetCode = 1; } else { // TODO: 在此处为应用程序的行为编写代码。 CAdoConnection AdoConnection; CAdoCommand AdoCommand; AdoConnection.ConnectingString = "Provider=SQLOLEDB;Network Address=127.0.0.1;Initial Catalog=临时数据库"; AdoConnection.UserName = "sa"; AdoConnection.PassWord = "sa"; if (AdoConnection.Connected == FALSE) AdoConnection.Connected = TRUE; AdoCommand.CommandType = adCmdText; AdoCommand.CommandText = string("INSERT INTO ") + string(argv[1]) + string(" (name) VALUES ('ghb')"); AdoCommand.m_AdoConnection = &AdoConnection; for (int i = 0; i<10000; i++) AdoCommand.Execute(); AdoConnection.Connected = FALSE; } CoUninitialize(); ct = CTime::GetCurrentTime(); text.Format("%d分%d秒", ct.GetMinute(), ct.GetSecond()); file << argv[1] << "结束时间:" << text << endl; return nRetCode; }
// b.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "b.h" #include <fstream> using namespace std; #ifdef _DEBUG #define new DEBUG_NEW #endif // 唯一的应用程序对象
CWinApp theApp; using namespace std; int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0; ofstream file("test.txt",std::ios::app); CTime ct; CString temp; ct = CTime::GetCurrentTime(); temp.Format("%d分%d秒", ct.GetMinute(), ct.GetSecond()); file << "主console程序开始时间:" << temp << endl; // 初始化 MFC 并在失败时显示错误 if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) { // TODO: 更改错误代码以符合您的需要 _tprintf(_T("致命错误: MFC 初始化失败\n")); nRetCode = 1; } else { // TODO: 在此处为应用程序的行为编写代码。 CString command, TableName; CString str; TableName = "table总"; str = CString("E:\\OutPut\\c\\c\\Debug\\c.exe ") + TableName; STARTUPINFO LargeSi = {0}; LargeSi.cb = sizeof(STARTUPINFO); PROCESS_INFORMATION LargePf; ::CreateProcess(NULL, str.GetBuffer(), NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &LargeSi, &LargePf); for (int i=1; i<=20; i++) { temp.Format("%d", i); TableName = CString("table") + temp; str = CString("E:\\OutPut\\a\\a\\Debug\\a.exe ") + TableName; //AfxMessageBox(str); STARTUPINFO si = {0}; si.cb = sizeof(STARTUPINFO); PROCESS_INFORMATION pf; ::CreateProcess(NULL, str.GetBuffer(), NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pf); } } ct = CTime::GetCurrentTime(); temp.Format("%d分%d秒", ct.GetMinute(), ct.GetSecond()); file << "主console程序结束时间:" << temp << endl; return nRetCode; }
// c.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "c.h" #include "DataAccess.h" #include <fstream> using namespace std; #ifdef _DEBUG #define new DEBUG_NEW #endif // 唯一的应用程序对象
CWinApp theApp; using namespace std; int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0; ofstream file("test.txt",std::ios::app); CTime ct; CString text; ct = CTime::GetCurrentTime(); text.Format("%d分%d秒", ct.GetMinute(), ct.GetSecond()); file << argv[1] << "开始时间:" << text << endl; CoInitialize(NULL); // 初始化 MFC 并在失败时显示错误 if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) { // TODO: 更改错误代码以符合您的需要 _tprintf(_T("致命错误: MFC 初始化失败\n")); nRetCode = 1; } else { // TODO: 在此处为应用程序的行为编写代码。 CAdoConnection AdoConnection; CAdoCommand AdoCommand; AdoConnection.ConnectingString = "Provider=SQLOLEDB;Network Address=127.0.0.1;Initial Catalog=临时数据库"; AdoConnection.UserName = "sa"; AdoConnection.PassWord = "sa"; if (AdoConnection.Connected == FALSE) AdoConnection.Connected = TRUE; AdoCommand.CommandType = adCmdText; AdoCommand.CommandText = string("INSERT INTO ") + string(argv[1]) + string(" (name) VALUES ('ghb')"); AdoCommand.m_AdoConnection = &AdoConnection; for (int i = 0; i<200000; i++) AdoCommand.Execute(); AdoConnection.Connected = FALSE; } CoUninitialize(); ct = CTime::GetCurrentTime(); text.Format("%d分%d秒", ct.GetMinute(), ct.GetSecond()); file << argv[1] << "结束时间:" << text << endl; return nRetCode; }

|