MySQL由于它本身的小巧和操作的高效, 在数据库应用中越来越多的被采用.我在开发一个P2P应用的时候曾经使用MySQL来保存P2P节点,由于P2P的应用中,结点数动辄上万个,而且节点变化频繁,因此一定要保持查询和插入的高效.以下是我在使用过程中做的提高效率的三个有效的尝试.

使用statement进行绑定查询

使用statement可以提前构建查询语法树,在查询时不再需要构建语法树就直接查询.因此可以很好的提高查询的效率. 这个方法适合于查询条件固定但查询非常频繁的场合.

使用方法是:

•  绑定, 创建一个MYSQL_STMT变量,与对应的查询字符串绑定,字符串中的问号代表要传入的变量,每个问号都必须指定一个变量.

•  查询, 输入每个指定的变量, 传入MYSQL_STMT变量用可用的连接句柄执行.

代码如下:

//1.绑定

bool CDBManager::BindInsertStmt(MYSQL * connecthandle)

{

//作插入操作的绑定

MYSQL_BIND insertbind[FEILD_NUM];

if(m_stInsertParam == NULL)

m_stInsertParam = new CHostCacheTable;

m_stInsertStmt = mysql_stmt_init(connecthandle);

//构建绑定字符串

char insertSQL[SQL_LENGTH];

strcpy(insertSQL, "insert into HostCache(SessionID, ChannelID, ISPType, "

"ExternalIP, ExternalPort, InternalIP, InternalPort) "

"values(?, ?, ?, ?, ?, ?, ?)");

mysql_stmt_prepare(m_stInsertStmt, insertSQL, strlen(insertSQL));

int param_count= mysql_stmt_param_count(m_stInsertStmt);

if(param_count != FEILD_NUM)

return false;

//填充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))

return false;

return true;

}

随机的获取记录

在某些数据库的应用中, 我们并不是要获取所有的满足条件的记录,而只是要随机挑选出满足条件的记录. 这种情况常见于数据业务的统计分析,从大容量数据库中获取小量的数据的场合.

有两种方法可以做到

1. 常规方法,首先查询出所有满足条件的记录,然后随机的挑选出部分记录.这种方法在满足条件的记录数很多时效果不理想.

2. 使用limit语法,先获取满足条件的记录条数, 然后在sql查询语句中加入limit来限制只查询满足要求的一段记录. 这种方法虽然要查询两次,但是在数据量大时反而比较高效.

示例代码如下:

//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;

如何提高mysql查询效率_如何提高MySQL查询效率相关推荐

  1. 提高mysql查询速度_如何提高数据库查询速度

    1.用程序中, 保证在实现功能的基础上,尽量减少对数据库的访问次数: 通过搜索参数,尽量减少对表的访问行数,最小化结果集,从而减轻网络负担: 能够分开的操作尽量分开处理,提高每次的响应速度: 在数据窗 ...

  2. mysql 加快命中_合理配置MySQL缓存 提高缓存命中率

    众所周知,系统读取数据时,从内存中读取要比从硬盘上速度要快好几百倍.故现在绝大部分应用系统,都会最大程度的使用缓存(内存中的一个存储区域),来提高系统的运行效率.MySQL数据库也不例外.在这里,笔者 ...

  3. mysql 多表 查询慢_详解Mysql多表联合查询效率分析及优化

    1. 多表连接类型1. 笛卡尔积(交叉连接) 在MySQL中可以为CROSS JOIN或者省略CROSS即JOIN,或者使用','  如: SELECT * FROM table1 CROSS JOI ...

  4. mysql in 原理_深入理解MySql子查询IN的执行和优化

    IN为什么慢? 在应用程序中使用子查询后,SQL语句的查询性能变得非常糟糕.例如: SELECT driver_id FROM driver where driver_id in (SELECT dr ...

  5. mysql分页原理_转:mysql分页原理和高效率的mysql分页查询语句

    (转自:http://www.jb51.net/article/46015.htm) 以前我在mysql中分页都是用的 limit 100000,20这样的方式,我相信你也是吧,但是要提高效率,让分页 ...

  6. linux mysql 查看缓存_详解MySQL查询缓存

    查询缓存是指存储使用SELECT语法查询到的返回到客户端的文本.当相同的请求再次发生时,会从查询缓存中获取数据,而非再执行一遍查询.查询缓存是共享Session会话的,所以一个客户端的请求可能与另一个 ...

  7. mysql query 查询失败_如何在mysql进行查询缓存及失败的解决方法

    都知道函数在使用前需要弄清楚参数的属性,这样才能对函数的使用有较好的了解.有些小伙伴学习了查询缓存后,直接进行了下一步的实战操作.这里小编想提醒大家,开始操作之前一定要先设置参数,不然就会出现问题.下 ...

  8. mysql子查询设置_什么是mysql子查询?如何利用子查询进行过滤?

    子查询 MySQL 4.1引入了对子查询的支持,所以要想使用本章描述的SQL,必须使用MySQL 4.1或更高级的版本. SELECT语句 是SQL的查询.迄今为止我们所看到的所有 SELECT 语句 ...

  9. 怎样开启mysql慢检查_如何开启mysql的慢查询

    原文:http://www.cnblogs.com/zhangjing0502/archive/2012/07/30/2615570.html Linux查看mysql 安装路径 一.查看文件安装路径 ...

最新文章

  1. java automapper 使用_19.AutoMapper 之开放式泛型(Open Generics)
  2. 合作伙伴说 | 一人行快,众人行远,与网易共建万亿新生态
  3. k8s多节点(接单节点继续)
  4. JSP实战型程序连载:通用数据库连接JavaBean
  5. android listview 滑动条显示_第七十六回:Android中UI控件之RecyclerView基础
  6. 关于cmd输入python查看版本号与安装版本不一致的奇怪现象
  7. ****CentOS下安装JDK1.7
  8. 【MATLAB】三维曲线(plot3)
  9. Django的cmdb探索与开发(三)
  10. CentOS基本的命令与快捷建
  11. 用例图中三种关系详解(转)
  12. 使用Rufus制作LINUX启动安装U盘(成功)
  13. 二学位计算机基础试题,计算机基础知识附试题().doc
  14. 统计遗传学:第二章,统计分析概念
  15. python实践_机器学习:Python实践 (魏贞原) 高清pdf完整版[124MB]
  16. ARM裸机--看门狗定时器
  17. 大数据破获网售假耐克案
  18. angular的 #
  19. 七年级计算机考试知识点,七年级语文重点笔记 必考知识
  20. 《中国综合算力指数》《中国算力白皮书》《中国存力白皮书》《中国运力白皮书》在首届算力大会上重磅发出

热门文章

  1. ios 自动打包命令_通过命令行xcodebuild编译打包iOS应用
  2. 深度解读SSH免密登录
  3. python建立FTP服务器
  4. Android studio 去除软件运行时顶部原有的蓝色/绿色框
  5. 使用 PyMOL 将靶点与配体复合物中的靶点和配体拆出来
  6. 给定一个整数序列,求中位数
  7. placeholder和assign速度对比
  8. [抄]外部奖励对内在动机的侵蚀
  9. 【Qt教程】1.11 - Qt5 标准对话框QMessageBox(关于、错误、信息、警告、问题、颜色、字体、文件对话框)
  10. AHT20温湿度传感器STM32-I2C驱动,替代DHT11/DHT12/AM2320/SHT20/SHT30,IIC代码兼容AHT10/15-MEMS温湿度传感器