前言

之所以写这篇文章,是源于以前看过的关于sql语句优化的帖子,里面明确提到了在sql语句中不要使用 * 来做查询,就像下面的规则中说的

2、尽量避免使用select *,返回无用的字段会降低查询效率。如下:SELECT * FROM t 优化方式:使用具体的字段代替*,只返回使用到的字段。

  

但是中国有句姥话叫“尽信书不如无书”,难道在sql查询语句中使用星号就真的慢的要死,难道加索引也不行?带着这些个疑问,我进行了一些测试。结果发现,江湖传说未必真的靠得住。那具体测试情况是咋样的呢?下面且听我给各位看官慢慢分解。

  事先声明,本文是抛砖文,只进行测试,不做原理分析(要不然篇幅太长,各位看官估计要看睡着了)。本文的一切测试均以实际测试数据为准,拒绝假大空。

测试环境准备

我这次测试的系统环境如下:

  • Win10系统
  • Mysql5.7.26 64位版本,使用默认的InnoDB存储引擎

  然后我准备了一张tb_item表,用来存放测试数据,数据是我跟朋友要的一些商品信息数据。

  下图是tb_item表的结构

  tb_item表中的部分数据

  我将从以下几个方面去进行测试:

  • count查询
  • 联表查询
  • 分页查询

  好,闲话不多说,马上开整。

一.count查询

在count查询操作中,又分为两种情况,不带where条件的count查询,和带where条件的count查询。那我们就依次来测试一下。

1. 不带where条件的count查询

  我们先来测试一下统计整个表的记录数。首先给大家剧透一下,tb_item表一共有300万条数据。执行 SELECT COUNT(*) FROM tb_item,结果如下图所示

  可以看到,查询时间是7秒多。如果是配置一般的机器,估计会更慢。显然,统计整张表的数据量,使用星号貌似是不行的。

  那有没有办法可以优化一下呢?当然有啊,而且我都给大家测试好了。在tb_item表中有一个 status 字段,不知道大家注意到了没有

  我们发现,这个字段的长度才占一个varchar。那如果我们修改一下刚才的sql,改成

  SELECT COUNT(STATUS) FROM tb_item

  又会如何呢?我们执行一下这条sql,看一下结果

  可以看到,这次的查询时间是4秒多,快了将近一半。

  如果我们给 status 字段加个索引,结果又会怎样呢?那我们就加个索引试试。执行

  CREATE INDEX idx_tb_item_status ON tb_item(STATUS)

  然后我们再执行一下 SELECT COUNT(STATUS) FROM tb_item,结果如下图

  这次的查询时间是0.9秒,不到1秒。

  从一开始的7秒多到现在的不到1秒,查询时间缩短了85%。这个优化结果真是爽的一批啊。

2. 带where条件的count查询

  现在我们再试一下使用星号执行带where条件的查询操作会是个什么情况。我们简单一些,就查询价格小于1000块钱的商品数据。

  执行 SELECT COUNT(*) FROM tb_item t WHERE t.price<1000,结果如下图

  查询时间是6秒多。那我们给price字段加上索引后,再看看是个什么情况。执行下面的sql给price字段加索引

  CREATE index idx_tb_item_price ON tb_item(price)

  然后再次执行 SELECT COUNT(*) FROM tb_item t WHERE t.price<1000,结果如下图

  各位朋友,你们没有看错,加了索引之后,查询时间确实只有0.28秒。这查询效率提升了 99% 啊,简直爽得不要不要的。

  那如果我们将星号换成长度只有一个varchar的 status 字段,情况又会是咋样的呢?我们来试一下

  是的,你没看错,这次查询又花了6秒多的时间。也就是说,price字段的索引失效了。

  看来带where条件的情况下,直接指定具体字段还不如直接用星号呢。

  刚才我们只测试了带一个查询条件的情况,下面我们再来试试带多个查询条件的情况。这次我查询price大于1000,sellerid(品牌代码)字段是oppo的数据。预期查询时间小于1秒

  查询时间6秒多,不能接受。那我先给sellerid字段上个索引再试试

  查询时间5秒,还是太慢。那就上个组合索引,给price和sellerid字段加个组合索引再试试。

  这次的查询时间是1秒多,虽然已经算不错了,但是还是没有达到我们预期的结果。而且我总不能增加一个查询条件,就改一次索引吧?

  所以,对于这种百万级别数据的多条件查询的情况,最好的解决办法就是上一个数据检索系统,比如lucence或者elastic search,然后把数据导入到数据检索系统中,让它帮mysql完成数据的条件检索,Mysql只提供数据的详情查询服务。而且,像es这样的系统还带有分词功能,可以轻松通过关键词实现数据的检索。这比使用mysql的like操作来检索数据,效率不知道要高多少倍。所以,专业的事情还是交给专业的系统去干。别跟我说公司没钱,上不起es。数据量达到300w的业务,你跟我说没钱?

二.联表查询

  刚才我们测试了在count查询操作中使用星号的情况,但是都是针对tb_item这一张表的操作。在实际的业务中,更多的是进行联表查询的操作。其中一个典型的业务场景,就是字典代码联表查询。比如在tb_item表中有一个sellerid字段,如下图

我们使用group by 加distinct关键字,看一下这个字段都有些什么内容

  可以看出来,这都是些品牌的英文或者汉语拼音。那样的话,我们就可以创建一张品牌信息表tb_seller_info,用来存放品牌的字典码和名称。tb_seller_info表的表结构如下图

  下图是表中的数据

  有了这张表,我们就可以做联表查询了。首先我们先来测试一下联表count查询tb_item表中“小米”公司的产品数据。执行下面的sql

  SELECT COUNT(*) FROM tb_item t INNER JOIN tb_seller_info si ON t.sellerid=si.sellerid WHERE si.sellername='小米'

  结果如下图

  查询时间是2秒。现在,我们给tb_item表中的sellerid字段加个索引,再测试一下

  可以看到,这次查询只用了0.35秒。提升效果十分地明显。

  如果我们把星号换成某个具体的字段,比如id字段,又是什么情况呢?我们试一下

  可以看到,查询时间和使用星号的情况差不多。

  那如果我们不做count查询,而是查询具体的数据呢?

  这一下查询时间就变成了将近7秒。OMG。我们得继续想办法优化了。我们先试试给tb_item表的sellerid字段加个索引试试。

  可以看到,查询时间是6秒多,还是不理想。那么我们把星号换成查询id字段再试试

  嘿,只查询id字段,竟然不到1秒就搞定了。各位亲们,看到这个,你们有没有想到什么?是不是觉得在id字段上建个hash索引,然后再搞个子查询,就OK了?说实话,我也想这样干。但是理想很美好,现实却很蛋疼。因为mysql5.7默认的InnoDB存储引擎不支持创建hash类型的索引。

  那有人可能会说了,用那个MEMORY存储引擎啊,那个支持创建hash类型的索引。那如果我告诉你,这个存储引擎是非事务安全的,你还想用吗?

  那么,我们就真的一点办法都没有了吗?哈哈,如果真的一点办法都没有,那我肯定就写不下去了啊。既然遇到问题了,总得解决不是。这里我先把图放出来,勾引勾引你们

  查询时间0.055秒,这个结果你们觉得爽不爽?

  细心的朋友肯定看到了,我的这个sql中使用了分页查询。所以把联表查询改造成使用子查询,再结合分页查询,效果立马就出来了。由此也引出了我要写的第三部分内容,分页查询。

三.分页查询

提到这个,很多朋友的第一印象肯定是,页数越大,查询速度越慢。大家的感觉是对的,确实如此,我们可以先来测试一下。比如我从第200万条记录开始,查询10条记录

  查询时间3秒多,如果是配置一般的机器,估计时间会更长。

  关于分页查询如何优化,百度上一艘一大把,我这里就不废话了,直接上图

  可见,分页查询的优化,也是使用了联表和子查询。回想刚才第二部分的联表查询,是不是就感觉豁然开朗了呢?(分页查询可是很多系统经常使用的功能呢)。

总结

  通过一系列的测试,可以看出来,在sql查询中,并非不是不能使用星号的。只要根据实际情况,合理搭配使用索引,子查询等优化方法,用星号反而能让我们少写不少代码。而且不用在添加表字段后,再去修改相应的sql查询语句。当然,如果再搭配sql查询分析器去做针对性的优化,那就更完美了。

  所以,古人诚不欺我,“尽信书不如无书”,说得太对了。必须向前辈们致敬一下。

  今天做测试用的数据已上传到百度云,朋友们想自己测试娱乐一下的可以去下载。测试数据文件是个sql脚本文件,可以整库导入。百度云链接如下

链接:https://pan.baidu.com/s/1bWNvIyIviC_2swG3rSd3Fg

提取码:f3of

转载于:https://www.cnblogs.com/johntsu/p/11386251.html

mysql查询语句中使用星号真的慢的要死?相关推荐

  1. MySQL查询语句中的IN 和Exists 对比分析

    背景介绍 最近在写SQL语句时,对选择IN 还是Exists 犹豫不决,于是把两种方法的SQL都写出来对比一下执行效率,发现IN的查询效率比Exists高了很多,于是想当然的认为IN的效率比Exist ...

  2. MyBatis + MyBatis Plus + MySQL——查询语句中字段名为MySQL关键字问题解决方案

    问题描述 ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your ...

  3. php无法查询mysql字母,php – 无法在Multi MYSQL查询语句中获取结果

    ==已解决== 我从以下帖子中获得此查询: 我在phpMyAdmin上试了一下,看到了我想要但无法获取的结果. $query = "SET @order_id := '', @order_t ...

  4. mysql查询语句 变量_mysql查询语句中用户变量的使用

    先上代码吧 SELECT `notice`.`id` , `notice`.`fid` , `notice`.`has_read` , `notice`.`notice_time` , `notice ...

  5. mysql五大子句_MySQL的查询语句中可以使用以下哪个子句来表示分组查询

    [多选题]人类行为遗传学工作者倾向于把人的行为遗传分为哪几类 [填空题]MySQL的连接操作包括内连接.( )和交叉连接. [判断题]社会生活类尤其是人文风光类纪录片的解说则多用文学. 散文手法, 既 ...

  6. left join 最后一条_一条Mysql查询语句的西天取经之路,你真的了解吗?

    数据库,大家都不陌生,这是程序员的基本技能了.当然,我们更多时候只是去了解如何使用数据库,而对数据库一些底层原理却比较陌生,今天我们来了解一下,一条数据库查询语句的取经之路. 基本分层 个人认为,My ...

  7. Mysql 子查询 (查询语句中带查询语句)

    子查询:指一个"正常查询语句"中的某个部分(比如select部分,from 部分,where 部分)又出现了查询的一种查询形式,比如: select * from 表名 where ...

  8. mysql 数据库里查询语句中不等于的两种写法

    mysql 数据库里查询语句中不等于的两种写法 ps:本人亲测,阿里云2核4G5M的服务器性价比很高,新用户一块多一天,老用户三块多一天,最高可以买三年,感兴趣的可以戳一下:阿里云折扣服务器 1.my ...

  9. mysql 中like用法_mysql查询语句中like 的用法

    1.常见用法: (1)搭配%使用 %代表一个或多个字符的通配符,譬如查询字段name中以大开头的数据: (2)搭配_使用 _代表仅仅一个字符的通配符,把上面那条查询语句中的%改为_,会发现只能查询出一 ...

  10. java mysql语句_java mysql查询语句怎么写

    展开全部 1:使用SHOW语句找出在服务器上当前存在什么数据32313133353236313431303231363533e4b893e5b19e31333363373766库: mysql> ...

最新文章

  1. 解决html5 audio iphone,ipd,safari不能自动播放问题
  2. UWP 响应键盘组合快捷键
  3. 【启智树NOIP模拟】生存【父子分治】
  4. python打开火狐浏览器打不开网页_PHP让指定网页只能在微信内置浏览器打开 附代码...
  5. webbrowser设置横向打印_C# 日常记录:指定打印机/纸张/纸盒(静默打印)(不弹窗打印)WinForm篇...
  6. hive币涨幅空间大吗_自动消防水炮只能安装在大空间场所吗
  7. 计算机参观企业心得,走进联想 感悟联想——北航MBA参观联想集团总部
  8. 云原生落地困挑战无处不在?我选Serverless
  9. DN安卓2014版(5-9)
  10. Linux Shell脚本测试案例(一)
  11. 梦幻西游网页版服务器互通吗,梦幻西游网页版开服伙伴
  12. caj文件打不开显示内存不足_U盘能显示文件大小但打开没有任何文件 - 卡饭网...
  13. matlab时域数据转频域,从时域和频域来解析傅里叶变换(含代码和性质)
  14. iphonex适配游戏_Unity+iPhoneX适配方案
  15. 禁用浏览器的后退按钮
  16. npm 中报错3 errors and 3 warnings potentially fixable with the`--fix` option.
  17. Unity小地图的实现
  18. 二进制炸弹实验bomb-whu 拆弹
  19. TreeGrid(树形表格)
  20. 详讲全排列算法,及解决数字搭积木问题

热门文章

  1. PTA数组后五道演讲比赛中有10个评委打分(实型数据,十分制分数)一维数组中,然后输入欲删除数x,最后删除数组中值为x的元素并输出,键盘输入一个4×4阶的矩阵,编程输出它的转置矩阵。
  2. 大数据智能分析的未来发展趋势
  3. android switch的使用方法,Android UI控件Switch的使用方法
  4. MSM8953修改开机动画
  5. C语言实现埃拉托斯特尼筛法
  6. 对于自组织团队的一些思考
  7. word输入公式快捷键
  8. 怎么复制图片的html代码,修改设置让你轻松复制网页文字或图片
  9. php微商城微信支付教程,微信支付接口配置教程(微商城版)
  10. android audiomixer,Android多媒体:AudioMixer