龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 数据库类 > MySQL 技术 >

提高MySQL查询效率的三个技巧(1)(2)

时间:2011-04-12 23:18来源:未知 作者:admin 点击:
分享到:
示例代码如下: //1.常规的方法 //性能瓶颈,10万条记录时,执行查询140ms, 获取结果集500ms,其余可忽略 int CDBManager::QueryHostCache(MYSQL* connecthandle, char * channelid

示例代码如下:

//1.常规的方法
//性能瓶颈,10万条记录时,执行查询140ms, 获取结果集500ms,其余可忽略
int CDBManager::QueryHostCache(MYSQL* connecthandle, char * channelid,

int ISPtype, CDBManager::CHostCacheTable * &hostcache)
{    
char selectSQL[SQL_LENGTH];
memset(selectSQL, 0, sizeof(selectSQL));
sprintf(selectSQL,"select * from HostCache where ChannelID = '%s'

and ISPtype = %d", channelid, ISPtype);
if(mysql_real_query(connecthandle, selectSQL, strlen(selectSQL)) != 0)   //检索
return 0;
//获取结果集
m_pResultSet = mysql_store_result(connecthandle);
if(!m_pResultSet)   //获取结果集出错
return 0;
int iAllNumRows = (int)(mysql_num_rows(m_pResultSet));     

///<所有的搜索结果数
//计算待返回的结果数
int iReturnNumRows = (iAllNumRows <= RETURN_QUERY_HOST_NUM)?

iAllNumRows:RETURN_QUERY_HOST_NUM;
if(iReturnNumRows <= RETURN_QUERY_HOST_NUM)
{
//获取逐条记录
for(int i = 0; i{
//获取逐个字段
m_Row = mysql_fetch_row(m_pResultSet);
if(m_Row[0] != NULL)
strcpy(hostcache[i].sessionid, m_Row[0]);
if(m_Row[1] != NULL)
strcpy(hostcache[i].channelid, m_Row[1]);
if(m_Row[2] != NULL)
hostcache[i].ISPtype      = atoi(m_Row[2]);
if(m_Row[3] != NULL)
hostcache[i].externalIP   = atoi(m_Row[3]);
if(m_Row[4] != NULL)
hostcache[i].externalPort = atoi(m_Row[4]);
if(m_Row[5] != NULL)
hostcache[i].internalIP   = atoi(m_Row[5]);
if(m_Row[6] != NULL)
hostcache[i].internalPort = atoi(m_Row[6]);             
}
}
else
{
//随机的挑选指定条记录返回
int iRemainder = iAllNumRows%iReturnNumRows;    ///<余数
int iQuotient = iAllNumRows/iReturnNumRows;      ///<商
int iStartIndex = rand()%(iRemainder + 1);         ///<开始下标 
//获取逐条记录
for(int iSelectedIndex = 0; iSelectedIndex < iReturnNumRows; iSelectedIndex++)
{
mysql_data_seek(m_pResultSet,

iStartIndex + iQuotient * iSelectedIndex);
m_Row = mysql_fetch_row(m_pResultSet);
if(m_Row[0] != NULL)
strcpy(hostcache[iSelectedIndex].sessionid, m_Row[0]);
if(m_Row[1] != NULL)
strcpy(hostcache[iSelectedIndex].channelid, m_Row[1]);
if(m_Row[2] != NULL)
hostcache[iSelectedIndex].ISPtype      = atoi(m_Row[2]);
if(m_Row[3] != NULL)
hostcache[iSelectedIndex].externalIP   = atoi(m_Row[3]);
if(m_Row[4] != NULL)
hostcache[iSelectedIndex].externalPort = atoi(m_Row[4]);
if(m_Row[5] != NULL)
hostcache[iSelectedIndex].internalIP   = atoi(m_Row[5]);
if(m_Row[6] != NULL)
hostcache[iSelectedIndex].internalPort = atoi(m_Row[6]);
}
}
//释放结果集内容
mysql_free_result(m_pResultSet);
return iReturnNumRows;
}

//2.使用limit版
int CDBManager::QueryHostCache(MYSQL * connecthandle, char * channelid,

unsigned int myexternalip, int ISPtype, CHostCacheTable * hostcache)
{
//首先获取满足结果的记录条数,再使用limit随机选择指定条记录返回
MYSQL_ROW row;
MYSQL_RES * pResultSet;
char selectSQL[SQL_LENGTH];
memset(selectSQL, 0, sizeof(selectSQL));

sprintf(selectSQL,"select count(*) from HostCache

where ChannelID = '%s' and ISPtype = %d", channelid, ISPtype);
if(mysql_real_query(connecthandle, selectSQL, strlen(selectSQL)) != 0)   //检索
return 0;
pResultSet = mysql_store_result(connecthandle);
if(!pResultSet)      
return 0;
row = mysql_fetch_row(pResultSet);
int iAllNumRows = atoi(row[0]);
mysql_free_result(pResultSet);
//计算待取记录的上下范围
int iLimitLower = (iAllNumRows <= RETURN_QUERY_HOST_NUM)?
0:(rand()%(iAllNumRows - RETURN_QUERY_HOST_NUM));
int iLimitUpper = (iAllNumRows <= RETURN_QUERY_HOST_NUM)?
iAllNumRows:(iLimitLower + RETURN_QUERY_HOST_NUM);
//计算待返回的结果数
int iReturnNumRows = (iAllNumRows <= RETURN_QUERY_HOST_NUM)?
iAllNumRows:RETURN_QUERY_HOST_NUM;

//使用limit作查询
sprintf(selectSQL,"select SessionID, ExternalIP,

ExternalPort, InternalIP, InternalPort "
"from HostCache where ChannelID = '%s' and ISPtype = %d limit %d, %d"
, channelid, ISPtype, iLimitLower, iLimitUpper);
if(mysql_real_query(connecthandle, selectSQL, strlen(selectSQL)) != 0)   //检索
return 0;
pResultSet = mysql_store_result(connecthandle);
if(!pResultSet)
return 0;
//获取逐条记录
for(int i = 0; i{
//获取逐个字段
row = mysql_fetch_row(pResultSet);
if(row[0] != NULL)
strcpy(hostcache[i].sessionid, row[0]);
if(row[1] != NULL)
hostcache[i].externalIP   = atoi(row[1]);
if(row[2] != NULL)
hostcache[i].externalPort = atoi(row[2]);
if(row[3] != NULL)
hostcache[i].internalIP   = atoi(row[3]);
if(row[4] != NULL)
hostcache[i].internalPort = atoi(row[4]);            
}
//释放结果集内容
mysql_free_result(pResultSet);
return iReturnNumRows;
}

使用连接池管理连接

在有大量节点访问的数据库设计中,经常要使用到连接池来管理所有的连接。

一般方法是:建立两个连接句柄队列,空闲的等待使用的队列和正在使用的队列。

当要查询时先从空闲队列中获取一个句柄,插入到正在使用的队列,再用这个句柄做数据库操作,完毕后一定要从使用队列中删除,再插入到空闲队列。


精彩图集

赞助商链接