主要为了看一下,多个进程多表对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;
}