如何提高mysql查询效率_如何提高MySQL查询效率
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查询效率相关推荐
- 提高mysql查询速度_如何提高数据库查询速度
1.用程序中, 保证在实现功能的基础上,尽量减少对数据库的访问次数: 通过搜索参数,尽量减少对表的访问行数,最小化结果集,从而减轻网络负担: 能够分开的操作尽量分开处理,提高每次的响应速度: 在数据窗 ...
- mysql 加快命中_合理配置MySQL缓存 提高缓存命中率
众所周知,系统读取数据时,从内存中读取要比从硬盘上速度要快好几百倍.故现在绝大部分应用系统,都会最大程度的使用缓存(内存中的一个存储区域),来提高系统的运行效率.MySQL数据库也不例外.在这里,笔者 ...
- mysql 多表 查询慢_详解Mysql多表联合查询效率分析及优化
1. 多表连接类型1. 笛卡尔积(交叉连接) 在MySQL中可以为CROSS JOIN或者省略CROSS即JOIN,或者使用',' 如: SELECT * FROM table1 CROSS JOI ...
- mysql in 原理_深入理解MySql子查询IN的执行和优化
IN为什么慢? 在应用程序中使用子查询后,SQL语句的查询性能变得非常糟糕.例如: SELECT driver_id FROM driver where driver_id in (SELECT dr ...
- mysql分页原理_转:mysql分页原理和高效率的mysql分页查询语句
(转自:http://www.jb51.net/article/46015.htm) 以前我在mysql中分页都是用的 limit 100000,20这样的方式,我相信你也是吧,但是要提高效率,让分页 ...
- linux mysql 查看缓存_详解MySQL查询缓存
查询缓存是指存储使用SELECT语法查询到的返回到客户端的文本.当相同的请求再次发生时,会从查询缓存中获取数据,而非再执行一遍查询.查询缓存是共享Session会话的,所以一个客户端的请求可能与另一个 ...
- mysql query 查询失败_如何在mysql进行查询缓存及失败的解决方法
都知道函数在使用前需要弄清楚参数的属性,这样才能对函数的使用有较好的了解.有些小伙伴学习了查询缓存后,直接进行了下一步的实战操作.这里小编想提醒大家,开始操作之前一定要先设置参数,不然就会出现问题.下 ...
- mysql子查询设置_什么是mysql子查询?如何利用子查询进行过滤?
子查询 MySQL 4.1引入了对子查询的支持,所以要想使用本章描述的SQL,必须使用MySQL 4.1或更高级的版本. SELECT语句 是SQL的查询.迄今为止我们所看到的所有 SELECT 语句 ...
- 怎样开启mysql慢检查_如何开启mysql的慢查询
原文:http://www.cnblogs.com/zhangjing0502/archive/2012/07/30/2615570.html Linux查看mysql 安装路径 一.查看文件安装路径 ...
最新文章
- java automapper 使用_19.AutoMapper 之开放式泛型(Open Generics)
- 合作伙伴说 | 一人行快,众人行远,与网易共建万亿新生态
- k8s多节点(接单节点继续)
- JSP实战型程序连载:通用数据库连接JavaBean
- android listview 滑动条显示_第七十六回:Android中UI控件之RecyclerView基础
- 关于cmd输入python查看版本号与安装版本不一致的奇怪现象
- ****CentOS下安装JDK1.7
- 【MATLAB】三维曲线(plot3)
- Django的cmdb探索与开发(三)
- CentOS基本的命令与快捷建
- 用例图中三种关系详解(转)
- 使用Rufus制作LINUX启动安装U盘(成功)
- 二学位计算机基础试题,计算机基础知识附试题().doc
- 统计遗传学:第二章,统计分析概念
- python实践_机器学习:Python实践 (魏贞原) 高清pdf完整版[124MB]
- ARM裸机--看门狗定时器
- 大数据破获网售假耐克案
- angular的 #
- 七年级计算机考试知识点,七年级语文重点笔记 必考知识
- 《中国综合算力指数》《中国算力白皮书》《中国存力白皮书》《中国运力白皮书》在首届算力大会上重磅发出
热门文章
- ios 自动打包命令_通过命令行xcodebuild编译打包iOS应用
- 深度解读SSH免密登录
- python建立FTP服务器
- Android studio 去除软件运行时顶部原有的蓝色/绿色框
- 使用 PyMOL 将靶点与配体复合物中的靶点和配体拆出来
- 给定一个整数序列,求中位数
- placeholder和assign速度对比
- [抄]外部奖励对内在动机的侵蚀
- 【Qt教程】1.11 - Qt5 标准对话框QMessageBox(关于、错误、信息、警告、问题、颜色、字体、文件对话框)
- AHT20温湿度传感器STM32-I2C驱动,替代DHT11/DHT12/AM2320/SHT20/SHT30,IIC代码兼容AHT10/15-MEMS温湿度传感器