MySQL社区

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
查看: 2036|回复: 3
打印 上一主题 下一主题

一个关于查询语句优化类的问题

[复制链接]
跳转到指定楼层
1#
发表于 2015-11-2 13:40:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 griffin702 于 2015-11-2 13:59 编辑

小弟新手,最近学习优化查询语句时发现一个弱弱的问题,不知哪位大神能否帮忙给一下比较精准的解释,万分感谢.先看一段我最开始些的一段查询语句:
首先需要计算出在第二天留存下来仍在活动的玩家数量(其中id1,time为log库下resource表中的字段,id2,CreateTime为role库下player表中的字段)
  1. select count(distinct id1) from log.resource
  2. where time BETWEEN date_add('2015-09-22 00:00:00', interval '1' day) and date_add('2015-09-22 23:59:59', interval '1' day)
  3. and id1 in (select id2 from role.player
  4. where CreateTime between '2015-09-22 00:00:00' and '2015-09-22 23:59:59')
复制代码

然后小弟看了不少优化的建议,得到一个初步的优化方案:先将子查询改为连接查询.
而偏偏第一次动手优化时出现了极大的反差,也许不是方案错,可能是小弟自己写错或者其他等原因,不过还是希望大神帮忙解惑一下,下面看我修改后的语句(当然修改过后,得到的答案是没错的):
select count(distinct b.id1) from
(
select player.id2,player.CreateTime
from role.player
where player.CreateTime between '2015-09-22 00:00:00' and '2015-09-22 23:59:59'
) a
inner join
(
select resource.id1,resource.time
from log.resource
where resource.time between date_add('2015-09-22 00:00:00', interval '1' day) and date_add('2015-09-22 23:59:59', interval '1' day)
) b
on b.id1 = a.id2


由于小弟之前些的是存储过程,而这一个查询仅仅是存储过程中的一段小查询,拿来做实验而已,所以以上用的时间是一个函数的方式,而效果是一样的.

本文中的疑惑重点不在于此,而是2个语句本身应该是修改后的执行时间应比之前的要快,可最后却实际上变慢了,关键是还慢了不少.

之前执行时间 1.5 ,修改后执行时间 2.12

当然,2个表里都做全了必须的索引.

用explain查询也看过了,疑惑的是连接查询多出了2行未使用索引.

哪位大神帮忙看看,感谢!


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏 分享淘帖 顶 踩
2#
发表于 2015-11-6 16:28:04 | 只看该作者
1.第2句明显比第1句有冗余字段了。
2.现在子查询已经进行过优化,除非驱动表不合理。
3#
 楼主| 发表于 2015-11-11 14:07:15 | 只看该作者
nycle 发表于 2015-11-6 16:28
1.第2句明显比第1句有冗余字段了。
2.现在子查询已经进行过优化,除非驱动表不合理。

谢谢,明白了.请问现在子查询进行过优化的程度可以达到效率优于联结表查询吗?

4#
 楼主| 发表于 2015-11-11 15:05:13 | 只看该作者
nycle 发表于 2015-11-6 16:28
1.第2句明显比第1句有冗余字段了。
2.现在子查询已经进行过优化,除非驱动表不合理。
  1. select count(distinct id1) from log.resource
  2.          where time BETWEEN date_add('2015-09-22 00:00:00', interval '1' day) and date_add('2015-09-22 23:59:59', interval '1' day)
  3.          and id1 in ( select id2 from role.player
  4.                                where CreateTime between '2015-09-22 00:00:00' and '2015-09-22 23:59:59' )
  5. #执行时间1.17

  6. select count(distinct b.id1) from
  7. (select player.id2 from role.player where player.CreateTime between '2015-09-22 00:00:00' and '2015-09-22 23:59:59') a left join
  8. (select resource.id1 from log.resource where resource.time between date_add('2015-09-22 00:00:00', interval '1' day) and date_add('2015-09-22 23:59:59', interval '1' day)) b
  9. on a.id2 = b.id1
  10. #执行时间1.24

  11. select count(distinct resource.id1) from role.player left join log.resource
  12. on player.id2 = resource.id1
  13. where resource.time BETWEEN date_add('2015-09-22 00:00:00', interval '1' day) and date_add('2015-09-22 23:59:59', interval '1' day)
  14. and player.CreateTime between '2015-09-22 00:00:00' and '2015-09-22 23:59:59'
  15. #执行时间1.59
复制代码
3条语句,查询目的相同,执行时间如上,其中第2条语句按你的指正,去除了冗余字段,但最终得到的结果仍没有第1条子查询来的快.
是否证明了你说的第2点,现在子查询进行了优化,优化后的效率已经超过了联结表查询呢?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|申请友链|小黑屋|Archiver|手机版|MySQL社区 ( 京ICP备07012489号   
联系人:周生; 联系电话:13911732319

GMT+8, 2024-5-4 12:24 , Processed in 0.067895 second(s), 22 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表