提高MySQL 查询效率的三个技巧第1/2页
时间:2020-11-02 13:24 作者:admin610456
mysql/' target='_blank'>mysql由于它本身的小巧和操作的高效,在数据库应用中越来越多的被采用.我在开发一个P2P应用的时候曾经使用MySQL来保存P2P节点,由于P2P的应用中,结点数动辄上万个,而且节点变化频繁,因此一定要保持查询和插入的高效.以下是我在使用过程中做的提高效率的三个有效的尝试.
l使用statement进行绑定查询
使用statement可以提前构建查询语法树,在查询时不再需要构建语法树就直接查询.因此可以很好的提高查询的效率.这个方法适合于查询条件固定但查询非常频繁的场合.
使用方法是:
绑定,创建一个MYSQL_STMT变量,与对应的查询字符串绑定,字符串中的问号代表要传入的变量,每个问号都必须指定一个变量.
查询,输入每个指定的变量,传入MYSQL_STMT变量用可用的连接句柄执行.
代码如下:
//1.绑定
boolCDBManager::BindInsertStmt(MYSQL*connecthandle)
{
//作插入操作的绑定
MYSQL_BINDinsertbind[FEILD_NUM];
if(m_stInsertParam==NULL)
m_stInsertParam=newCHostCacheTable;
m_stInsertStmt=mysql_stmt_init(connecthandle);
//构建绑定字符串
charinsertSQL[SQL_LENGTH];
strcpy(insertSQL,"insertintoHostCache(SessionID,ChannelID,ISPType,"
"ExternalIP,ExternalPort,InternalIP,InternalPort)"
"values(?,?,?,?,?,?,?)");
mysql_stmt_prepare(m_stInsertStmt,insertSQL,strlen(insertSQL));
intparam_count=mysql_stmt_param_count(m_stInsertStmt);
if(param_count!=FEILD_NUM)
returnfalse;
//填充bind结构数组,m_sInsertParam是这个statement关联的结构变量
memset(insertbind,0,sizeof(insertbind));
insertbind[0].buffer_type=MYSQL_TYPE_STRING;
insertbind[0].buffer_length=ID_LENGTH/*-1*/;
insertbind[0].buffer=(char*)m_stInsertParam->sessionid;
insertbind[0].is_null=0;
insertbind[0].length=0;
insertbind[1].buffer_type=MYSQL_TYPE_STRING;
insertbind[1].buffer_length=ID_LENGTH/*-1*/;
insertbind[1].buffer=(char*)m_stInsertParam->channelid;
insertbind[1].is_null=0;
insertbind[1].length=0;
insertbind[2].buffer_type=MYSQL_TYPE_TINY;
insertbind[2].buffer=(char*)&m_stInsertParam->ISPtype;
insertbind[2].is_null=0;
insertbind[2].length=0;
insertbind[3].buffer_type=MYSQL_TYPE_LONG;
insertbind[3].buffer=(char*)&m_stInsertParam->externalIP;
insertbind[3].is_null=0;
insertbind[3].length=0;
insertbind[4].buffer_type=MYSQL_TYPE_SHORT;
insertbind[4].buffer=(char*)&m_stInsertParam->externalPort;
insertbind[4].is_null=0;
insertbind[4].length=0;
insertbind[5].buffer_type=MYSQL_TYPE_LONG;
insertbind[5].buffer=(char*)&m_stInsertParam->internalIP;
insertbind[5].is_null=0;
insertbind[5].length=0;
insertbind[6].buffer_type=MYSQL_TYPE_SHORT;
insertbind[6].buffer=(char*)&m_stInsertParam->internalPort;
insertbind[6].is_null=0;
insertbind[6].is_null=0;
//绑定
if(mysql_stmt_bind_param(m_stInsertStmt,insertbind))
returnfalse;
returntrue;
}
//2.查询
boolCDBManager::InsertHostCache2(MYSQL*connecthandle,char*sessionid,char*channelid,intISPtype,\
unsignedinteIP,unsignedshorteport,unsignedintiIP,unsignedshortiport)
{
//填充结构变量m_sInsertParam
strcpy(m_stInsertParam->sessionid,sessionid);
strcpy(m_stInsertParam->channelid,channelid);
m_stInsertParam->ISPtype=ISPtype;
m_stInsertParam->externalIP=eIP;
m_stInsertParam->externalPort=eport;
m_stInsertParam->internalIP=iIP;
m_stInsertParam->internalPort=iport;
//执行statement,性能瓶颈处
if(mysql_stmt_execute(m_stInsertStmt))
returnfalse;
returntrue;
}
l随机的获取记录
在某些数据库的应用中,我们并不是要获取所有的满足条件的记录,而只是要随机挑选出满足条件的记录.这种情况常见于数据业务的统计分析,从大容量数据库中获取小量的数据的场合.
有两种方法可以做到
1.常规方法,首先查询出所有满足条件的记录,然后随机的挑选出部分记录.这种方法在满足条件的记录数很多时效果不理想.
2.使用limit语法,先获取满足条件的记录条数,然后在sql查询语句中加入limit来限制只查询满足要求的一段记录.这种方法虽然要查询两次,但是在数据量大时反而比较高效.
示例代码如下:
//1.常规的方法
//性能瓶颈,10万条记录时,执行查询140ms,获取结果集500ms,其余可忽略
intCDBManager::QueryHostCache(MYSQL*connecthandle,char*channelid,intISPtype,CDBManager::CHostCacheTable*&hostcache)
{
charselectSQL[SQL_LENGTH];
memset(selectSQL,0,sizeof(selectSQL));
sprintf(selectSQL,"select*fromHostCachewhereChannelID='%s'andISPtype=%d",channelid,ISPtype);
if(mysql_real_query(connecthandle,selectSQL,strlen(selectSQL))!=0)//检索
return0;
//获取结果集
m_pResultSet=mysql_store_result(connecthandle);
if(!m_pResultSet)//获取结果集出错
return0;
intiAllNumRows=(int)(mysql_num_rows(m_pResultSet));///<所有的搜索结果数
//计算待返回的结果数
intiReturnNumRows=(iAllNumRows<=RETURN_QUERY_HOST_NUM)?iAllNumRows:RETURN_QUERY_HOST_NUM;
if(iReturnNumRows<=RETURN_QUERY_HOST_NUM)
{
//获取逐条记录
for(inti=0;i<iReturnNumRows;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
{
//随机的挑选指定条记录返回
intiRemainder=iAllNumRows%iReturnNumRows;///<余数
intiQuotient=iAllNumRows/iReturnNumRows;///<商
intiStartIndex=rand()%(iRemainder+1);///<开始下标
//获取逐条记录
for(intiSelectedIndex=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);
returniReturnNumRows;
}
12下一页阅读全文
(责任编辑:admin)