这两天实习项目遇到一个网页加载巨慢的问题(10多秒),然后定位到是一个MySQL查询特别慢的语句引起的:

SELECT *

FROM (

SELECT DISTINCT t.vc_date, t.c_bankno, t.vc_bankacco, t.vc_moneytype, t.en_totalbala

, t.en_usablebala, t1.vc_nameinbank, date_format(t.D_IMPORTTIME, '%Y-%m-%d %H:%i:%S') AS D_IMPORTTIME

, t.vc_fundcode, t.c_datamode, t.vc_taskid, t.id, t.vc_projectname

, t.vc_projectcode, t1.c_accotype

, (

SELECT IF(vc_occurtime IS NULL, DATE_FORMAT(vc_occurdate, '%Y-%m-%d'), DATE_FORMAT(CONCAT(vc_occurdate, vc_occurtime), '%Y-%m-%d %H:%i:%S')) AS tradeTime

FROM tbanktradedetail_view

WHERE vc_bankacco = t.vc_bankacco

) AS d_tradetime, t3.vc_entry_caption AS C_ACCOTYPE_STR, t5.vc_entry_caption AS VC_BANKNAME, t4.vc_entry_caption AS VC_MONEYTYPE_STR

FROM tbankaccobala t

INNER JOIN tbankaccoinfo t1 ON t.vc_bankacco = t1.vc_bankacco

INNER JOIN (

SELECT vc_entry_value, vc_entry_caption

FROM ot_dic_tdictionaryentry

WHERE vc_entry_no = '5087'

) t3

ON t1.c_accotype = t3.vc_entry_value

INNER JOIN (

SELECT vc_entry_value, vc_entry_caption

FROM ot_dic_tdictionaryentry

WHERE vc_entry_no = '1004'

) t4

ON t1.VC_MONEYTYPE = t4.vc_entry_value

INNER JOIN (

SELECT vc_entry_value, vc_entry_caption

FROM ot_dic_tdictionaryentry

WHERE vc_entry_no = '1014'

) t5

ON t.c_bankno = t5.vc_entry_value

WHERE 1 = 1

AND t.id IN (

-- this query will take 4.6s:

-- SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY d_importtime DESC), ',', 1)

-- FROM tbankaccobala

-- GROUP BY vc_bankacco

-- but the following query only takes 1.1s:

SELECT hhhh from(

SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY d_importtime DESC), ',', 1) as hhhh

FROM tbankaccobala

GROUP BY vc_bankacco

) as sbstr

-- 对IN的子查询做二次查询

)

) t

WHERE 1 = 1

ORDER BY t.D_IMPORTTIME DESC

抽出查询慢关键部分:

SELECT *

FROM (

SELECT DISTINCT t.vc_date, t.c_bankno, t.vc_bankacco, t.vc_moneytype, t.en_totalbala

-- 此处省略选择多个列语句

FROM tbankaccobala t

-- 此处省略多张表连表查询语句

WHERE 1 = 1

AND t.id IN (

-- 这个查询需要3s:

SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY d_importtime DESC), ',', 1)

FROM tbankaccobala

GROUP BY vc_bankacco

)

) t

这个语句导致前端页面10多秒才有响应(但MySQL执行显示要4.6秒,phpMyAdmin也是10秒左右响应,为何?)

IN子查询语句优化

把IN语句里面的内容改成下面这样,只在外层再加一个select,就把3s的查询缩短为0.006s:

SELECT hhhh from(

SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY d_importtime DESC), ',', 1) as hhhh

FROM tbankaccobala

GROUP BY vc_bankacco

) as sbstr

-- 对IN的子查询做二次select,或者把IN改为JOIN都可以解决速度奇慢的问题

原语句空行处省略了一系列的其他表和 INNER JOIN 语句。一开始怀疑是多表的JOIN操作导致速度变慢,但删去JOIN变成上面这段注释掉的语句之后,速度依然非常慢,显示要3s,于是猜测 IN 才是导致速度变慢的主要因素,改后只要0.006s,啧…

EXPLAIN 未优化的语句:

(相关子查询是使用外部查询中的值的子查询)

EXPLAIN 优化的语句:

我的理解:优化前,子查询是相关子查询,对于外部产生的每个值,都要执行一次子查询;优化后,子查询不再是相关子查询,只需要执行一次子查询并缓存中间结果,外部查到的每个值去缓存的中间结果里比对一下就行了。

(有人说是能不能用索引的原因——这么说应该是不对的)

完整查询的后端响应速度对比:

前:

后:

索引优化

对于这么小的数据规模,时间还是太长了… 看前面explain执行计划的截图,嗯,没有索引…

给t1的vc_bankacco加上索引之后

解释执行计划:

查询和网页响应用时大幅缩短:

再看sql里还有三个join:

用的都是ot_dic_tdictionaryentry这张表的t4.vc_entry_value字段,那么试着给这个字段也加上索引吧,然后用时如下:

是的,时间反而变长了!

explain执行计划:

所以变慢原因是:

没加vc_entry_value的索引时,会先用vc_entry_no选出一个数量很小的表,再和t1做join,

而加了vc_entry_value的索引之后,MySQL就把这个索引用了起来,join语句被优化为先FirstMatch(ot_dic_tdictionaryentry),这产生了一个1713*1713=2934369行的中间结果(笛卡尔乘积),然后才使用vc_entry_no进行where过滤。

所以索引不能乱加啊,加错了反而会导致性能下降!这个示例里的查询要加索引只能在vc_entry_no上索引,而不能在vc_entry_value上!

这个示例中主要提升是IN子查询语句的优化。在使用索引的情况下,对IN子查询做优化前后的查询时间分别是3.1s和0.16s

mysql in优化_MySQL的一次优化记录 (IN子查询和索引优化)相关推荐

  1. mysql嵌套子查询索引_SQL 子查询,索引优化

    场景 索引优化 单列索引 多列索引 索引覆盖 排序 场景 我用的数据库是mysql5.6,下面简单的介绍下场景 课程表 create table Course( c_id int PRIMARY KE ...

  2. mysql多表连接 索引_MySQL多表查询之外键、表连接、子查询、索引

    一.外键: 1.什么是外键 2.外键语法 3.外键的条件 4.添加外键 5.删除外键 1.什么是外键: 主键:是唯一标识一条记录,不能有重复的,不允许为空,用来保证数据完整性 外键:是另一表的主键, ...

  3. mysql模糊查询之索引优化

    mysql模糊查询之索引优化 三表连查之模糊查询索引优化 注:具体用法10和11步骤. 1.t_project表 DROP TABLE IF EXISTS `t_project`; CREATE TA ...

  4. mysql易百_MySQL如何选择随机记录?

    在本教程中,您将学习从MySQL的数据库表中选择随机记录的各种技术方法. 有时我们需要从表中选择随机记录,例如: 在博客中选择一些随机帖子,并在侧栏中显示. 在"每日报价"窗口小部 ...

  5. mysql查询与索引优化2

    1.性能分析 Mysql Query Optimizer mysql内部有自己的优化器,当收到sql时,会按它自己认为最好的优化方式去优化 Mysql常见瓶颈 CPU:CPU在饱和的时候一般发生在数据 ...

  6. 记一次mysql优化 not in, not exits, left join 子查询

    在某次业务逻辑中写到如下逻辑:查询学校级别的未拦截弹窗记录.而弹窗设备表(t_block_blacklist_device)有四种类型(1:学校级黑名单 2:设备级别黑名单 3:略 4:学校级白名单 ...

  7. mysql 子查询添加索引_mysql – 你能索引子查询吗?

    我有一个表和一个如下所示的查询.有关工作示例,请参阅此 SQL Fiddle. SELECT o.property_B, SUM(o.score1), w.score FROM o INNER JOI ...

  8. mysql插入性能_mysql 数据量大时插入和查询性能

    现在mysql中有数据33.8w的数据,然后做查询和更新或插入操作,速度很慢,基本100条数据就要1.68s.好慢啊,我要测试一下,到底慢在哪?能不能提高点速度? 参考一篇博文:http://blog ...

  9. mysql子查询走索引吗_MySQL中in子查询会导致无法使用索引问题(转)

    MySQL的测试环境 测试表如下 create tabletest_table2 ( idint auto_increment primary key, pay_idint, pay_timedate ...

最新文章

  1. 【学习笔记】超简单的多项式求指(含泰勒展开式、牛顿迭代完成证明)
  2. akaze特征匹配怎么去掉不合适的点_图像匹配几种常见算法与实践
  3. 『中级篇』k8s的NodePort类型Service以及Label的简单实用(68)
  4. FlipView和自定义值转换器
  5. [pytorch、学习] - 4.6 GPU计算
  6. telegram定时消息_ActiveMQ(18):Message之延迟和定时消息投递
  7. 业务链路升级中如何做数据洞察?
  8. 新版CSDN编辑器示例(代码及显示样式)
  9. linux 统计文件字节和行数,Linux命令-统计文件中的字节数、字数、行数:wc
  10. MQL5 编程基础:数组
  11. 7.3万字肝爆Java8新特性,我不信你能看完!(建议收藏)
  12. 几种简单电路知识汇总
  13. 目前人工智能的主要研究方向都有哪些?
  14. 华侨大学计算机组成原理期末考试试题,计算机组成原理试卷A卷答案
  15. 爱优芒角逐“剧场风”,腾讯为何“按兵不动”
  16. 请连接虚拟服务器来配置,datastage8.7客户端连接虚拟服务器 无法连接显示 (用户名和/或密码不正确。如果使用了凭证映射,请检查凭证映射用户名和密码是否配置正确。 (80011))...
  17. JAVA如何自定义布局单选框,5分钟DIY一个自定义单选框单选按钮
  18. 实时内核μC/OS-II下的网络监控系统的设计
  19. 五大派玩家角逐移动资讯市场,微博如何成“另类”?
  20. 为什么要学C语言及C语言存在的意义,有人经常犹豫学不学C语言

热门文章

  1. typora打开pdf文件提示文件过大_Win7/Win10拷贝到U盘容量足够却提示文件过大的解决方法...
  2. git 使用writer_GitHub - Vpredictor/WriterFly: [QT/C++] 写作天下,为作家创造世界而生,执云作笔,诉尽平生意。...
  3. UE4角色Location远距离时动画抖动问题(float精度不够)解决方案
  4. matlab如何画一个平面,matlab 画平面
  5. 【转】OWIN是什么?
  6. python tempfile自动删除_Python tempfile模块生成临时文件和临时目录
  7. php elasticsearch 获取索引所有文档_Elasticsearch客户端主要方法的使用规则
  8. ArrayList、HashMap、HashSet是线程不安全的,高并发下如何解决?
  9. Python3 爬虫学习笔记 C17【爬虫框架 pyspider — 基本使用】
  10. 【Linux学习】强大的文本分析工具AWK