mysql查询时,offset过大影响性能的原因与优化方法
遇到的问题
我们大家都知道,mysql查询使用select命令,配合limit,offset参数可以读取指定范围的记录,但是offset过大影响查询性能的原因及优化方法,这次工作中因为要导出40W的数据遇到这个offset过大的问题,遍历写入excel的时间花了2个多小时。
准备测试数据表及数据
1、创建表
CREATE TABLE `member` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,`name` varchar(10) NOT NULL COMMENT '姓名',`gender` tinyint(3) unsigned NOT NULL COMMENT '性别',PRIMARY KEY (`id`),KEY `gender` (`gender`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2、插入1000000条记录
<?php
$pdo = new PDO("mysql:host=localhost;dbname=user","root",'');for($i=0; $i<1000000; $i++){$name = substr(md5(time().mt_rand(000,999)),0,10);$gender = mt_rand(1,2);$sqlstr = "insert into member(name,gender) values('".$name."','".$gender."')";$stmt = $pdo->prepare($sqlstr);$stmt->execute();
}
?>mysql> select count(*) from member;
+----------+
| count(*) |
+----------+
| 1000000 |
+----------+
1 row in set (0.23 sec)
分析offset过大影响性能的原因
1 、offset较小的情况
mysql> select * from member where gender=1 limit 10,1;
+----+------------+--------+
| id | name | gender |
+----+------------+--------+
| 26 | 509e279687 | 1 |
+----+------------+--------+
1 row in set (0.00 sec)mysql> select * from member where gender=1 limit 100,1;
+-----+------------+--------+
| id | name | gender |
+-----+------------+--------+
| 211 | 07c4cbca3a | 1 |
+-----+------------+--------+
1 row in set (0.00 sec)mysql> select * from member where gender=1 limit 1000,1;
+------+------------+--------+
| id | name | gender |
+------+------------+--------+
| 1975 | e95b8b6ca1 | 1 |
+------+------------+--------+
1 row in set (0.00 sec)
当offset较小时,查询速度很快,效率较高。
2、offset较大的情况
mysql> select * from member where gender=1 limit 100000,1;
+--------+------------+--------+
| id | name | gender |
+--------+------------+--------+
| 199798 | 540db8c5bc | 1 |
+--------+------------+--------+
1 row in set (0.12 sec)mysql> select * from member where gender=1 limit 200000,1;
+--------+------------+--------+
| id | name | gender |
+--------+------------+--------+
| 399649 | 0b21fec4c6 | 1 |
+--------+------------+--------+
1 row in set (0.23 sec)mysql> select * from member where gender=1 limit 300000,1;
+--------+------------+--------+
| id | name | gender |
+--------+------------+--------+
| 599465 | f48375bdb8 | 1 |
+--------+------------+--------+
1 row in set (0.31 sec)
当offset很大时,会出现效率问题,随着offset的增大,执行效率下降。
分析影响性能原因
select * from member where gender=1 limit 300000,1;
因为数据表是InnoDB,根据InnoDB索引的结构,查询过程为:
- 通过二级索引查到主键值(找出所有gender=1的id)。
- 再根据查到的主键值通过主键索引找到相应的数据块(根据id找出对应的数据块内容)。
根据offset的值,查询300001次主键索引的数据,最后将之前的300000条丢弃,取出最后1条。
所以,mysql查询时,offset过大影响性能的原因是多次通过主键索引访问数据块的I/O操作,如下图。
InnoDB与MyISAM引擎索引结构对比图
InnoDB有这个问题,而MYISAM索引结构与InnoDB不同,二级索引都是直接指向数据块的,因此没有此问题。
优化方法
根据上面的分析,我们知道查询所有字段会导致主键索引多次访问数据块造成的I/O操作。
因此我们先查出偏移后的主键,再根据主键索引查询数据块的所有内容即可优化。
mysql> select a.* from member as a inner join (select id from member where gender=1 limit 300000,1) as b on a.id=b.id;
+--------+------------+--------+
| id | name | gender |
+--------+------------+--------+
| 599465 | f48375bdb8 | 1 |
+--------+------------+--------+
1 row in set (0.08 sec)
所以最后我通过这个方式查询数据,百万级的数据基本都是毫秒级别的查询出结果,40W数据写入excel时间从2个多小时优化成20分钟,满满的成就感哈。
参考文章
:
- 转载from:https://blog.csdn.net/fdipzone/article/details/72793837
- sefault:https://segmentfault.com/p/1210000008951080/read
转载于:https://blog.51cto.com/onebig/2124954
mysql查询时,offset过大影响性能的原因与优化方法相关推荐
- MySQL查询中LIMIT的大offset导致性能低下浅析
这篇文章主要给大家介绍了关于MySQL查询中LIMIT的大offset导致性能低下的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起 ...
- MySQL查询时记录行号rownum MySQL查询显示行号MySQL查询显示行号MySQL流水号自MySQL自增行号
MySQL查询时记录行号rownum MySQL查询显示行号MySQL查询显示行号MySQL流水号自MySQL自增行号 一.前言 Oracle中有rownum,实现查询的时候记录行号,MySQL中没有 ...
- mysql大小写区分_详解MySQL查询时区分字符串中字母大小写的方法
如果你在mysql有唯一约束的列上插入两行值'A'和'a',Mysql会认为它是相同的,而在oracle中就不会.就是mysql默认的字段值不区分大小写?这点是比较令人头痛的事.直接使用客户端用sql ...
- 上传文件时$_FILES为空,可能的原因及解决方法
上传文件时$_FILES为空,可能的原因及解决方法 参考文章: (1)上传文件时$_FILES为空,可能的原因及解决方法 (2)https://www.cnblogs.com/i6010/articl ...
- SSH连接时出现Host key verification failed的原因及解决方法
SSH连接时出现Host key verification failed的原因及解决方法 参考文章: (1)SSH连接时出现Host key verification failed的原因及解决方法 ( ...
- MySQL:为什么用limit时,offset很大会影响性能
点击上方"朱小厮的博客",选择"设为星标" 后台回复"加群"加入公众号专属技术群 来源:rrd.me/fe8TT 一,前言 首先说明一下My ...
- mysql id用什么类型_mysql 证明为什么用limit时,offset很大会影响性能
首先说明一下MySQL的版本: mysql> select version(); +-----------+ | version() | +-----------+ | 5.7.17 | +-- ...
- oschina mysql limit_MySQL 用 limit 为什么会影响性能?
点击上方"武培轩",选择"设为星标" 技术文章第一时间送达! 一,前言 首先说明一下MySQL的版本: mysql> select version();+ ...
- MySQL查询时指定使用索引
在MySQL中,可以通过指定查询使用的索引来提高查询性能和优化查询执行计划.以下是一些常见的场景,可能需要考虑指定查询使用的索引: 查询性能问题:当一个查询在大表上运行缓慢时,可以考虑为该查询指定合适 ...
最新文章
- spark任务优先级设置:spark.yarn.priority
- SSD: Signle Shot Detector 用于自然场景文字检测
- 在 ubuntu 上编译 qtopia-2.2.0问题
- [转]打造自己的LINQ Provider(上):Expression Tree揭秘
- java heap_javaHeap的组成及GC监控
- php windows环境 安装 Apache-apollo + phpMQTT 实现发送 MQTT
- kali免杀工具shellter
- 如何将大硬盘对拷到小硬盘
- mathorcup历年优秀论文阿里云盘
- scheme语言编写运行
- 用python画写轮眼_创意scratch编程课:火影经典忍术,宇智波佐助的写轮眼!
- 有内鬼,终止换脸!用Landmarks Debug找出不老实的脸。
- 【汇正财经】什么是股权结构?
- SCSS迷你书(上)
- Visual2022安装步骤社区版,专业版or企业版安装(附注册码)(没有桌面图标的解决方法)
- 进程的概念与基本介绍
- AS打包的应用安装时解析包错误或没有签名
- WEB安全之:SQL Injection--DVWA环境测试
- node.js毕业设计安卓基于Android的超市会员管理系统开发(程序+APP+LW)
- NY8B062D 九齐单片机之ADC芯片
热门文章
- 洛谷 P1219 ---- 八皇后
- 关于eclipse web项目认不到用户库的问题
- python tfidf特征变换_Spark MLlib机器学习开发指南(4)--特征提取--TF-IDF
- linux系统终端more,一篇文章让你学透Linux系统中的more命令
- jdbc是java语言编写的类和接口_JDBC——Java语言连接数据库的标准
- appSettings 配置mysql_app.config数据库配置字符串的三种取法
- 晓庄学院计算机科学分数,南京晓庄学院计算机单招分数
- 计算机应用技术自我分析,计算机应用*个人自我鉴定
- linux使用u盘的过程是,图文详解Linux下使用U盘的方法
- java this() super()_java中的this和super